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

答え2

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"/>

または、これら2つのコマンドを組み合わせて

xmlstarlet fo -H file.xhtml 2>/dev/null |
    xmlstarlet ed -u '//img/@src' -v 'graphics/line.jpg'

準備ができたら、結果を一時ファイルに保存し、元のファイルを変更されたバージョンに置き換えます。 (または、元のファイルの名前をバックアップに変更し、それを入力として使用して元の名前のファイルを作成します。)

要素が複数ある場合は<img/>単に 。ただし、あなたの質問には、これらの可能性を効果的に解決するための詳細は不十分です。//imgsrc

答え3

努力する:

sed -i.bak 's/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g' *.xhtml


sed -i '.bak' --> sed -i.bak
'*.xhtml' --> *.xhtml

スラッシュをエスケープしたくない場合は、他のオプションはを使用することですrpl

Debian ベースのディストリビューションの場合:

sudo apt install rpl

rpl -b "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg" "graphics/line.jpg" *.xhtml

-b = backup

rpl マニュアル

答え4

また、これを試すことができますsed-iテスト中に適していないため、対応するフラグが含まれていません。

sed -E 's|(img src=").[^"]*(/.*)|\1graphics\2|' input_file

これにより、維持する必要がある一致をグループ化し、維持する必要がない一致を除外します。

(.*=.)- 最後の発生まですべてをグループ化=

.[^"]*- 除外された一致。[^"]最後の項目と一致し、/次の項目と一致するのを防ぐために使用されます。"

(/.*)- 最後の2番目のパターンまですべて/除外され、その後の残りのパターンは一致します。

\1graphics\2- 2つのグループゲームが作成され、順序に関係なく返すことができます。graphics後でハードコードする必要があるため、最初にグループ化された=一致が返されるとすぐに挿入できます。\1

|- データ自体に「/」スラッシュが含まれており、seds基本区切り記号と衝突するため、パイプを区切り記号として使用します。

出力

$ sed -E 's|(img src=").[^"]*(/.*)|\1graphics\2|' input_file
<img src="graphics/line.jpg"/>

関連情報