在文件中搜索字符串(从文件中获取),然后替换属于第一个匹配项的不同字符串的任何实例

在文件中搜索字符串(从文件中获取),然后替换属于第一个匹配项的不同字符串的任何实例

该班轮将搜索 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

相关内容