
ライナーは名前:0602を検索し、次の名前に達するまでType###のすべてのインスタンスをタイプ700に置き換えます。
sed '/Name: R0602/,/Name.*$/ s/type .*;/type 700;/' file2
このパッドに似たものを使用したいのですが、file1の名前リストを使用してfile2を検索したいと思います。 file1型の文字列を見つけたら、名前部分の終わりに達するまでstring2のすべてのインスタンスを置き換えてから、file1の次の行に対して同じことを行います。
ファイル1
Name: 0602
Name: 0603
Name: 0604
ファイル2:
# Name: R0601
Container 4 {
row 12 type 2 {
set 1 10 {
name "C4";
type 300;
}
set 11 20 {
name "C5";
type 100;
}
set 21 20 {
name "C6";
type 300;
}
set 31 40 {
name "C7";
type 200;
}
set 31 40 {
name "C7";
type 1200;
}
}
}
# Name: R0602
Container 5 {
row 12 type 2 {
set 1 10 {
name "C4";
type 300;
}
set 11 20 {
name "C5";
type 100;
}
set 21 20 {
name "C6";
type 300;
}
set 31 40 {
name "C7";
type 300;
}
set 31 40 {
name "C7";
type 1100;
}
}
}
# Name: R0603
Container 6 {
row 12 type 2 {
set 1 10 {
name "C4";
type 200;
}
set 11 20 {
name "C5";
type 100;
}
set 21 20 {
name "C6";
type 300;
}
set 31 40 {
name "C7";
type 500;
}
set 31 40 {
name "C7";
type 1100;
}
}
}
# Name: R0604
Container 6 {
row 12 type 2 {
set 1 10 {
name "C4";
type 200;
}
set 11 20 {
name "C5";
type 100;
}
set 21 20 {
name "C6";
type 300;
}
set 31 40 {
name "C7";
type 500;
}
set 31 40 {
name "C7";
type 1100;
}
}
}
# Name: R0605
Container 6 {
row 12 type 2 {
set 1 10 {
name "C4";
type 200;
}
set 11 20 {
name "C5";
type 100;
}
set 21 20 {
name "C6";
type 300;
}
set 31 40 {
name "C7";
type 500;
}
set 31 40 {
name "C7";
type 1100;
}
}
}
答え1
短い awk スクリプト
awk '
NR == FNR { names["R"$2]; next }
$2 == "Name:" { replace = ($3 in names) }
$1 == "type" && replace { sub(/type .*/, "type 700;") }
1
' file1 file2
NR と FNR は awk 組み込み変数です。 NRはこれまでに見た行の総数を計算します。 FNRは、現在のファイルからこれまでに見た行数です。NR == FNR
「最初のデータファイルで作業しています」を意味するawk慣用語です。現在のレコード数が合計レコード数と等しい唯一のファイルです。
したがって、最初のファイルを読み取るときは、2番目の列に「キー」を保存しようとします。in
後で使用する演算子を考えると、それを「名前」の連想配列のキーとして保存するのが便利な場所です。 2番目のファイルに対応する文字があるので、キーに文字「R」を追加しました。
その当時、$2 == "Name:"
私たちはある区域の上にいました。行の3番目の単語が最初のファイルに表示されたら、型の値を変更しようとします。 3番目の単語が連想配列のキーとして($3 in names)
表示されることを確認してください。names
存在する場合は、最初の単語が「type」の後続の行で置換を実行します。
スクリプトの最後の行が面白いです。1
awkに現在の行を印刷するように指示する別の慣用的な略語です。 awkプログラムはcondition {action}
一連のペアです。条件が満たされると、所与のタスクが実行される。条件を省略することができ、この場合、各行ごとに演算が実行されます。アクションブロックなしで条件を指定できます。この場合、デフォルトのアクションは現在の行を印刷することです。 awk は空の文字列と 0 を false として扱うので、1
条件は常に true です。もっと冗長に感じたら、もっと明確にするの{print}
ではなく書き留めます。1
答え2
GNU awkスクリプトは次のとおりです。
NR == FNR {
strt=1
}
strt == 0 {
if (match($0,/Name/)) {
id=substr($0,RSTART,length($0))
id=gensub("R","","g",id)
}
file2[id]=file2[id]"\n"$0
}
FNR == 1 && NR != 1 {
strt=0
file2[$0]=""
}
strt == 1 {
file1[$0]=$0
}
END {
for (i in file2) {
if (file1[i] != "") {
resp=gensub(/[[:blank:]]{5}type.*;/," type
700;","g",file2[i])
print resp
}
else {
print file2[i]
}
}
}
2つのファイルを別々の配列(ファイル1、ファイル2)に読み込みます(例:「名前:0603」)。最後に、file1に一致する配列file2を繰り返します。 file1にエントリがある場合は、パターンの一致と置換にgensubを使用し、そうでない場合はfile2のエントリのみを印刷します。
アクション:
awk -f scriptfile file1 file2