sedまたはexを使用して、ブロック(複数行コード)を新しいテキストブロック(コード)に置き換えるにはどうすればよいですか?


9

ファイル内のテキスト(シェルスクリプトコード)の大きなブロックを別のテキストブロックに置き換える必要があります。

sedを使用して複数行の文字列を置き換えるにどうすればよいですか?で答え antakマルチラインを置き換えることで答えブルースEdiger

しかし、私はそれらを使用するのにいくつかの問題を抱えています。

  1. antakは既に回答で言及していますが、ファイル全体(1h;2,$H;$!d;g;)をバッファにストリーミングすることは、メモリが過負荷になるため、大きなファイルにはお勧めできません。

  2. sedブロック機能を使用して、ブロック外のテキストを変更せずに保持できることを知っています。この機能を使いたい。でも使ったら

    sed -i '/marker1/,/marker2/s/.*/new text (code)/' filename
    

ストリームごとに新しいテキスト(コード)を繰り返し挿入します。したがって、視覚的ブロックを1つのストリームとして作成する必要があります。以前のantakによって提案されたものと同様のものを使用しますが、ブロックに対して(ファイル全体ではなく)行います。

  1. Bruce Edigerで述べたように、(ドット)exで始まる追加機能を試すことはできますが、新しいテキスト(コード)にはドットで始まる行が含まれており、追加構文のドットと見なすことができます。この状況でどのように使用できますか?a.

  2. ex'のdd行数'は複数の行を削除する可能性がありますが、/ marker1 /と/ marker2 /の間に固定されていない(可変の)行数のブロックがある場合、新しいテキスト(コード)で置き換える場合、方法それ ?


「ビジュアルブロック」という用語の使用は珍しくて混乱します。単に連続した完全な行のブロック(グループ)を意味しているのですか?
スコット

はい、混乱を避けるために質問を編集しています。
Gibies

置換テキストのソースは何ですか?それはファイルにあるのですか、それとも「プログラマの心の中でのみ」ですか?
don_crissti

これは、シェルスクリプトの状況に応じたパッチ用です。したがって、置換テキストのソースはプログラマーの心です(または、sedor exコマンドが機能するマスタースクリプト)。
Gibies

Don Crisstir置換テキストのソースがファイル内にある場合、別のファイルからテキストをコピーするためにread fileコマンドを使用しました。
Gibies

回答:


10

私はc hangeコマンドを使用することをお勧めします(これは基本的にa ppendと結合され deeleteですが、appendは、ここで希望する範囲の最後の行にのみ適用されます)。

sed -i '/marker1/,/marker2/c\
New text 1\
New text 2' filename

ここでsedは、インプレース編集にGNU の構文を使用しています(-i)。それc以外の点では、このコマンドは標準的で移植性があります。GNU sedサポート:

sed '/marker1/,/marker2/cNew text 1\
New text 2' filename

非標準の拡張として。

置換テキストでは、改行文字とバックスラッシュ文字を(バックスラッシュで)エスケープする必要があります。


changeコマンドは、どちらの場合sedex同じように機能します。どうもありがとうございました。
Gibies

「\」を回避し、ブルースエディガーマルチライン置換で提案した構文sedの場合のように、ここのドキュメントを使用する方法はありますか。ex
Gibies

rその質問に対する他の回答で説明されているコマンドを使用する場合は、バックスラッシュは必要ありません。hereドキュメントをでどのように使用するかわかりませんsed
G-Manは 'Reinstate Monica'を

8

GNU sedの使用

行マッチング3を開始し、行マッチングを継続する行を次のように置き換えるに5New Code

$ seq 8 | sed '/3/,/5/{/5/ s/.*/New Code/; t; d}'
1
2
New Code
6
7
8

範囲内/3/,/5/の行について、行が一致するかどうか5(これがグループの最後の行であることを意味するかどうか)をテストし、一致する場合は、insertを置換しNew Codeます。置換が行われた場合、tコマンドはsedにコマンドの最後にジャンプするよう指示します(この場合New Codeは出力されます)。そうでない場合、dコマンドはsedに行を削除するように指示します。

他のすべての行は通常どおり印刷されます。

ファイルをその場で変更するには、この-iオプションを使用できます。

sed -i.bak '/3/,/5/{/5/ s/.*/New Code/; t; d}' file

awkの使用

awkを使用して同じことを行うには:

$ seq 8 | awk '/3/,/5/{if (!f)print "New Code"; f=1; next}; 1'
1
2
New Code
6
7
8

awkコマンドは、範囲内の行を/3/,/5/特別に扱います。その範囲の行についてfは、ゼロかどうか(つまり、!f真の場合)をテストし、ゼロの場合は印刷New Codefて1に設定してから、残りのコマンドをスキップしてそのnext行にジャンプします。

範囲外の行の/3/,/5/場合、ジャンプは行われず1、行が印刷されます。詳しく1は、状態です。1はゼロではないため、条件はtrueと評価されます。条件に関連付けられているアクションがないため、行を印刷するというデフォルトのアクションが実行されます。したがって1、行印刷​​の省略形です。

ファイルをインプレースで変更するには、この-i inplaceオプションをGNU awk4.1以降で使用できます。

awk -i inplace '/3/,/5/{if (!f)print "New Code"; f=1; next} 1' file

涼しい。私はが苦手awkです、あなたのawk表現を少し説明してください
Rahul

1
@Rahulもちろん。awkコードの説明を追加しました。
John1024

1
ありがとうJohnこれはまさに私が探していたものです。
Gibies

削除ブロックがはるかに簡単で、最後の行に新しいものを追加しますsed '/3/,/4/d;/5/cNew Code' awk '/5/{print "New Code"}/3/,/5/{next}1'
コスタス

1

上記の議論に基づいて、私は ex

seq 15 > test1.txt
ex test1.txt << EOEX
/^7/,/^9/c
abcd
123
.xyz
hfr4
.
w!
q
EOEX
cat test1.txt

上記は与える

1
2
3
4
5
6
abcd
123
.xyz
hfr4
10
11
12
13
14
15

変更コマンドを認識し、ドットについて説明してくれたg-manに感謝します。両方とも、変更コマンド(削除コマンド、追加コマンドなど)sedexほぼ同様の構文を共有します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.