sed はイメージパスを置き換えます。

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これは適切ですか?

ベストアンサー1

この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属性の元の値がある場合、各ノードの各属性値を文字列に置き換えます。imggraphics/line.jpg/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg

このコマンドは、ジョブの結果を標準出力に書き込みますが、テスト後に対応する(または)オプションを使用して、期待どおりに機能することを確認xmlstarletできます。--inplace-L


タグが正しい無限imgのように見える場合は、まずXHTMLファイルをフィルタリングしてそれを元に戻すことができます。<img src="...">

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'

処理するファイルがすべてパターンと一致する場合、./*.xhtmlつまり.xhtmlファイル名のサフィックスがあり、現在のディレクトリにある場合は、上記のコマンドのいずれかを使用して単純なシェルループを使用してすべてのファイルを処理できます。 。

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 {} +

おすすめ記事