Bash gawk用于使用变量将包含图案的线替换为多行

Bash gawk用于使用变量将包含图案的线替换为多行,bash,awk,gawk,Bash,Awk,Gawk,我试图用一组行替换包含使用gawk的模式的行。比如说,文件aa包含 aaaa ccxyzcc aaaa ddxyzdd 我正在使用gawk将包含xyz的所有行替换为一组行111\n222,我更改的内容将包含: aaaa 111 222 aaaa 111 222 但是,如果我使用: gawk -v nm2="111\n222" -v nm1="xyz" '{ if (/nm1/) print nm2;else print $0}' "aa" 更改的内容显示: aaaa ccxyzcc aaa

我试图用一组行替换包含使用
gawk
的模式的行。比如说,文件
aa
包含

aaaa
ccxyzcc
aaaa
ddxyzdd
我正在使用gawk将包含xyz的所有行替换为一组行111\n222,我更改的内容将包含:

aaaa
111
222
aaaa
111
222
但是,如果我使用:

gawk -v nm2="111\n222" -v nm1="xyz" '{ if (/nm1/) print nm2;else print $0}' "aa"
更改的内容显示:

aaaa
ccxyzcc
aaaa
ddxyzdd

我需要包含
xyz
的整行代码,即
ccxyzcc
ddxyzdd
必须替换为
111
,后跟
222
。请提供帮助。

代码的问题是
/nm1/
试图将
nm1
作为模式而不是
nm1
变量中的值进行匹配

$ gawk -v nm2="111\n222" -v nm1="xyz" '$0 ~ nm1{print nm2; next} 1' aa
aaaa
111
222
aaaa
111
222
感谢@fedorqui的建议,
next
可以通过简单地覆盖与所需文本匹配的输入行内容来避免

gawk -v nm2="111\n222" -v nm1="xyz" '$0 ~ nm1{$0=nm2} 1' aa

使用GNU
sed的解决方案

$ nm1='xyz'
$ nm2='111\n222'
$ sed "/$nm1/c $nm2" aa
aaaa
111
222
aaaa
111
222

当使用
awk的
~
运算符时,
c
命令将删除行匹配模式并添加给定的文本,并且不需要在右侧提供文本regex

您的命令本身带有不正确语法的更正,类似于

gawk -v nm2="111\n222" -v nm1="xyz" '{ if ( $0 ~ nm1 ) print nm2;else print $0}' input-file
它产生输出

aaaa
111
222
aaaa
111
222
我会这样做:

$ cat aa
aaaa
ccxyzcc
aaaa
ddxyzdd
$ awk '{gsub(/.*xyz.*/, "111\n222")}1' aa
aaaa
111
222
aaaa
111
222
$ 

将变量作为模式传递给awk总是有点棘手

awk  -v nm2='111\n222'  '{if ($1 ~ /xyz/){ print nm2 } else {print}}'
将为您提供输出,但“xyz”模式现在已修复

将nm1作为shell变量传递也会起作用:

nm1=xyz
awk  -v nm2='111\n222'  '{if ($1 ~ /'$nm1'/){ print nm2 } else {print}}' aa

/nm1/
中,您试图匹配文本字符串“nm1”。这就是为什么要说
$0~nm1
来匹配变量
nm1
的内容。太好了!你也可以说
$0~nm1{$0=nm2}1
,这样就不需要
next
。并且用三元运算符对高尔夫球进行编码:
gawk-v nm2=“111\n222”-v nm1=“xyz”{打印$0~nm1?nm2:$0}文件