ディレクトリ内の複数の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
属性の元の値がある場合、各ノードの各属性値を文字列に置き換えます。img
graphics/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/>
単に 。ただし、あなたの質問には、これらの可能性を効果的に解決するための詳細は不十分です。//img
src
答え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
答え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"/>