1

「insert.txt」という名前のファイルがあります。次のようになります (または醜い):

ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>

そして、「STARTSTACKOVERFLOW」で区切られたターゲット ファイル (target.txt) 内のテキスト ブロックを「STOPSTACKOVERFLOW」に置き換えたいと考えています。(ここでは質問を少し単純化していますが、同じです)。

これを行うために使用するbashスクリプトは次のとおりです。

TARGETFILE=target.txt
SOURCEFILE=insert.txt
SOURCETXT="$(<$SOURCEFILE)"
DELIMTXT=$(printf "%q" "$SOURCETXT")

sed -i -e "/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/cSTARTSTACKOVERFLOW\n\n${DELIMTXT}\n\nSTOPSTACKOVERFLOW\n" $TARGETFILE

問題は、「target.txt」に貼り付けられたものが実際には ANSI-C で引用されていることです。

$'ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>'

$'' が追加されていることに注意してください。

その理由は、printf "%q" がこの引用スタイルを生成しているためです。私はそれを避けたいと思いますが、このファイルのすべての悪さを回避しなければならないので必要です。

bash と sed を使用して上記を行うより良い方法はありますか?

4

1 に答える 1

0

POSIX sed には、ファイルから読み取る「r」コマンドがあります。そう:

sed -i -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/r large.txt' target.txt

唯一の問題は、ファイルが 1 回読み込まれるか、開始行と停止行の間の行ごとに 1 回読み込まれるかです。行ごとに1回読み取られると思われます...そして余分な行を捨てる方法を考えるのは難しいです...しかし多分:

sed -i -e '/STOPSTACKOVERFLOW/r large.txt' \
       -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/d' target.txt

簡単なデモ

このバージョンでは、開始マーカーと終了マーカーが削除されています。

$ cat data
sdasas
adsasdas
start
more
more
end
sdasda
sdasdad
$ cat replace
replace1
replace2
replace3
$ sed -e '/^end$/r replace' -e '/start/,/end/d' data
sdasas
adsasdas
replace1
replace2
replace3
sdasda
sdasdad

開始マーカーと終了マーカーの保持

$ cat sedfile
/^end$/{
a\
start
r replace
a\
end
}
/^start$/,/^end$/d
$ sed -f sedfile data
sdasas
adsasdas
start
replace1
replace2
replace3
end
sdasda
sdasdad
$ 

これは面倒です。スクリプト用のファイルを使用せずに実行しようとはしませんが、必要に応じて実行できます。ただし、それはワンライナーではありません。

于 2010-10-26T18:31:21.623 に答える