sed 替換圖像的路徑
我需要替換目錄中多個 xhtml 文件中圖像的路徑。文件頭部分如下:
<?xml version="1.0" encoding="UTF-8"?> <html xml:lang="en-us" lang="en-us" xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:ns="http://www.w3.org/2001/10/synthesis"> <head>
試圖用
sed
命令來做,但它不起作用。可能由於特定的 sed 版本,但不確定。我有GNU sed 4.4
original path: <img src="/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg" I need replace to: <img src="graphics/line.jpg"
我試過了
sed -i '.bak' 's/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g' '*.xhtml'
它返回
sed: -e expression #1, char 1: unknown command: `.'
也試過
sed -i ' ' 's/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g' '*.xhtml' it return sed: can't read s/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g: No such file or directory sed: can't read *.xhtml: No such file or directory
sed
適合這個嗎?
該
sed
實用程序通常不適合編輯 XML 或 XHTML 文件。XML 是一種結構化的文件格式,而不是面向行的。與許多標準的 Unix 文本操作工具一樣,該sed
實用程序是面向行的,並且不會在沒有額外工作的情況下處理 XML 實體的編碼或解碼之類的事情。您的範例文件包含節點(更正為
/>
最後包含)<img src="/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg" />
由於節點內的空格(空格、製表符和換行符)是任意的,並且我們不知道
img
節點的更多屬性或其順序,因此使用 . 解析會很麻煩sed
。我們還必須確保不要在節點src
屬性之外的任何地方替換路徑名。img
使用命令行 XML 解析器執行此操作可能如下所示:
xmlstarlet ed \ -u '//img/@src[. = "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"]' \ -v 'graphics/line.jpg' file.xhtml
我們正在使用
xmlstarlet
一個相當知名的命令行 XML 解析器,如果屬性的原始值為 ,則將src
每個節點的每個屬性的值替換img
為字元串。graphics/line.jpg``/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg
該命令將操作結果寫入標準輸出,但您可以在測試後使用它的(or ) 選項
xmlstarlet
進行就地編輯,以確保它看起來像您期望的那樣工作。--inplace``-L
如果您的
img
標籤看起來像<img src="...">
,沒有正確的結尾,那麼您可以通過首先過濾您的 XHTML 文件來恢復xmlstarlet fo --recover --html file.xhtml
甚至可以設想表格上的管道
xmlstarlet fo --recover --html file.xhtml | xmlstarlet ed \ -u '//img/@src[. = "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"]' \ -v 'graphics/line.jpg'
如果您要處理的文件都與 pattern 匹配
./*.xhtml
,即,如果它們具有.xhtml
文件名後綴並且位於目前目錄中,那麼您將能夠使用上述任一命令使用簡單的 shell 循環來處理所有這些文件。for name in ./*.xhtml; do xmlstarlet ed --inplace \ -u '//img/@src[. = "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"]' \ -v 'graphics/line.jpg' "$name" done
請注意,這使用
--inplace
選項xmlstarlet
,它將修改文件而不進行備份。最好在備份數據上執行它。要在目錄層次結構中的所有 XHTML 文件上執行上述內容,即在具有多個子目錄的目錄中,您可以使用
find
.find . -type f -name '*.xhtml' -exec sh -c ' for name do xmlstarlet ed --inplace \ -u "//img/@src[. = \"/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg\"]" \ -v "graphics/line.jpg" "$name" done' sh {} +
如果它是 XHTML,您可以使用適當的 XML 編輯器對其進行編輯。這裡的優點是它不受文件佈局更改的影響
首先,將您的範例修改為 XML(畢竟它是一個 XHTML 文件),
<img src="/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"/>
如果您的源文件不是真正的 XHTML,您可以通過程式方式修復它
xmlstarlet format -H file.xhtml
您可以
src
使用以下命令編輯屬性xmlstarlet
:xmlstarlet edit --omit-decl --update '//img/@src' --value 'graphics/line.jpg' file.xhtml <img src="hello"/>
或者通過結合這兩個命令,
xmlstarlet fo -H file.xhtml 2>/dev/null | xmlstarlet ed -u '//img/@src' -v 'graphics/line.jpg'
準備好後,將結果放入臨時文件,然後用修改後的版本替換原始文件。(或者將原始文件重命名為備份,並將其用作輸入以創建具有原始名稱的文件。)
如果您有多個
<img/>
元素,則可以為它們提供結構路徑,而不僅僅是//img
. 如果您只想更改具有特定src
屬性值的那些也是可能的。但是您的問題中沒有足夠的細節來有效地解決這些可能性。