文件1
<filename1.txt> stringA string1
<filename2.txt> stringA string2
<filename2.txt> stringB string3
文件2
<filename1.txt> words and symbols < $ stringA words and symbols 9
<filename2.txt> more words and symbols % @ stringA words and symbols stringB
文件2已转换
<filename1.txt> words and symbols < $ string1 words and symbols 9
<filename2.txt> more words and symbols % @ string2 words and symbols string3
我的方法是循环遍历 File1 的各行来设置变量。因此,对于第 1 行,变量设置为:
filenamevar = <filename1.txt>
string_old_var = stringA
string_new_var = string1
然后 grep 与 filenamevar 和 string_old_var 匹配的行作为 sed 的输入。这就是我需要帮助的地方(除非你认为有更好的方法)。
目前最接近的是
grep -e "$filenamevar.*$string_old_var" File2.txt | sed s/$string_old_var/$string_new_var/ >> File2Transformed.txt
除了第二行输出两次外,其他都有效:
<filename1.txt> words and symbols < $ string1 words and symbols 9
<filename2.txt> more words and symbols % @ string2 words and symbols stringB
<filename2.txt> more words and symbols % @ stringA words and symbols string3
我也尝试过
grep -e "$filenamevar.*$string_old_var" File2 | sed s/$string_old_var/$string_new_var/
和
sed -i s/$string_old_var/$string_new_var/ $(grep -e "$filenamevar.*$string_old_var" File2)
但都没有产生预期的结果。
这是我正在使用的循环
Numlines=$(grep "" -c File1.txt)
for (( line=1; line<=$Numlines; line++ )) ; do
filenamevar=$(awk -v line=$line 'NR == line {print $1}' File1.txt)
string_old_var=$(awk -v line=$line 'NR == line {print $2}' File1.txt)
string_new_var=$(awk -v line=$line 'NR == line {print $3}' File1.txt)
# insert proper sed grep code to test here
done
答案1
如果你决定使用 shell 循环来实现这一点,你可以这样做
while read -r fname patt repl; do
sed -i.bak "/$fname/s/^$patt/$repl/" File2
done < File1
但请注意,如果任何字符串包含正则表达式特殊字符序列,它可能会以意想不到的方式中断。另一个选项(对特殊字符有相同的警告)可能是这样的
awk '{printf "/^%s/s/%s/%s/\n",$1,$2,$3}' File1 | sed -f- File2
它用于awk
将 File1 格式化为一系列命令,然后通过管道sed -f
修改 File2。
使用支持二维数组的 GNU awk (又名gawk
),您可以执行以下操作:
$ gawk '
NR==FNR {a[$1][$2] = $3; next}
$1 in a {for(i=2;i<=NF;i++) $i = $i in a[$1] ? a[$1][$i] : $i}
1
' File1 File2
<filename1.txt> words and symbols < $ string1 words and symbols 9
<filename2.txt> more words and symbols % @ string2 words and symbols string3
或者如果您需要保持对齐,请使用以下index
函数substr
:
$ gawk '
NR==FNR {a[$1][$2] = $3; next}
$1 in a {
for(s in a[$1]) {
mstart = index($0,s);
if(mstart > 0) $0 = substr($0,1,mstart-1) a[$1][s] substr($0,mstart+length(s))}
}
1
' File1 File2
<filename1.txt> words and symbols < $ string1 words and symbols 9
<filename2.txt> more words and symbols % @ string2 words and symbols string3
在 vanilla awk 中类似的东西,用 FS 分隔的字符串伪造二维数组:
mawk '
NR==FNR {a[$1 FS $2] = $3; next}
{
for(k in a) {
split(k,b);
if($1 == b[1]) {
mstart = index($0,b[2]);
if(mstart > 0) $0 = substr($0,1,mstart-1) a[k] substr($0,mstart+length(b[2]));
}
}
}
1
' File1 File2