该班轮将搜索 Name: 0602,然后用类型 700 替换 Type### 的任何实例,直到到达下一个 Name。
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 习语,意思是“我正在第一个数据文件中工作”——当前记录数等于总记录数的唯一文件。
因此,在读取第一个文件时,我们想要存储第二列中的“密钥”。考虑到in
我们稍后使用的运算符,将它们存储为“名称”关联数组的键是一个方便的地方。我将字母“R”添加到密钥中,因为第二个文件有该字母。
当 时$2 == "Name:"
,我们位于一个部分的顶部。如果在第一个文件中看到该行的第三个单词,我们希望替换类型值。($3 in names)
检查第三个单词是否作为键出现在names
关联数组中。如果存在,那么我们将对第一个单词是“type”的任何后续行执行替换。
脚本的最后一行很有趣。1
是指示 awk 打印当前行的另一种惯用简写。 awk 程序是一系列condition {action}
对:如果满足条件,则执行给定的操作。可以省略条件,在这种情况下,将对每一行执行该操作。可以在没有操作块的情况下给出条件,在这种情况下,默认操作是打印当前行。 awk 将空字符串和零视为假,因此1
条件始终为真。当我感觉更冗长时,我会写下来{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]
}
}
}
将两个文件读入单独的数组(文件1,文件2),例如“名称:0603”。最后,循环遍历与 file1 匹配的数组 file2。如果 file1 中有条目,则使用 gensub 进行模式匹配和替换,否则仅打印 file2 中的条目。
行动:
awk -f scriptfile file1 file2