Bash gawk和grep使用相同的模式,但需要对逃逸序列进行不同的处理
我有一个bash shell脚本(名为Bash gawk和grep使用相同的模式,但需要对逃逸序列进行不同的处理,bash,shell,awk,grep,gawk,Bash,Shell,Awk,Grep,Gawk,我有一个bash shell脚本(名为testawk),用于将包含模式(第一个参数)的行替换为一行或多行(第二个参数),并对第三个参数中给出的文件名进行操作。shell脚本如下所示: #!/bin/bash if grep -s "$1" "$3" > /dev/null; then gawk -v nm2="$2" -v nm1="$1" '{ if ($0 ~ nm1) print nm2;else print $0}' "$3" > "$3".bak mv "$3"
testawk
),用于将包含模式(第一个参数)的行替换为一行或多行(第二个参数),并对第三个参数中给出的文件名进行操作。shell脚本如下所示:
#!/bin/bash
if grep -s "$1" "$3" > /dev/null; then
gawk -v nm2="$2" -v nm1="$1" '{ if ($0 ~ nm1) print nm2;else print $0}' "$3" > "$3".bak
mv "$3".bak "$3"
fi
如果我有一个名为“aa”的文件,其中包含以下内容:
a;
b<*c;
aa包含:
x<*y;
b<*c;
aa
现在包含为(未更改的内容):
它可以匹配并显示:
b<*c;
而aa
不会得到更改的内容,因为:
a;
b<*c;
a;
b这应该符合我认为你的要求:
if awk -v nm2="$2" -v nm1="$1" 'index($0,nm1){f=1; $0=nm2} 1; END{exit !f}' "$3" > "${3}.bak"
then
mv "${3}.bak" "$3"
# do stuff with modified file "$3"
else
rm -f "${3}.bak"
# do stuff with unmodified file "$3"
fi
除了反斜杠之外,不需要逃避任何东西,如果您有反斜杠,我们可以以不同的方式处理。这应该满足您的要求:
if awk -v nm2="$2" -v nm1="$1" 'index($0,nm1){f=1; $0=nm2} 1; END{exit !f}' "$3" > "${3}.bak"
then
mv "${3}.bak" "$3"
# do stuff with modified file "$3"
else
rm -f "${3}.bak"
# do stuff with unmodified file "$3"
fi
除了反斜杠,不需要逃避任何东西,如果你有反斜杠,我们可以用不同的方式处理。首先,awk
已经进行了模式匹配,那么你真的需要两者都做吗?如果你做了,试着用-F
forgrep
告诉它把参数当作固定字符串,而不是模式,也可以使用-q
grep
的选项,而不是将stdout重定向到某个地方。当找到匹配项时,它会立即退出,因此速度也会更快…我认为gawk
有一个用于就地编辑的选项…@EricRenouf只是为了节省时间,grep和gawk都使用了,如果文件包含该模式,则使用gawk逐行进行编辑如果模式匹配(@Eric),则按原样放置或替换,并且要在gawk
中进行非regexp匹配,请使用index($0,string)>0
或仅使用index($0,string)
在像if
而不是0$pattern
OP这样的布尔上下文中:grep
也会“逐行”进行,因此grep
加gawk
总是比gawk
更昂贵。尽管如果你想保留原始文件和没有发现更改时的modtime,你可以使用gawk
return一个退出状态,指示它是否进行了更改。@Sundeep我认为gawk
4.1引入了-I inplace
作为一个选项,因此如果它是一个足够新的gawk
确实应该首先工作,awk
已经进行了模式匹配,那么你真的需要两者都做吗?如果你这样做,试着对g使用-F
rep
告诉它将参数视为固定字符串,而不是模式,也可以使用-q
选项grep
,而不是将stdout重定向到某个地方..当找到匹配项时,它会立即退出,因此速度也会更快..我认为gawk
有一个就地编辑的选项..@EricRenoufme,grep和gawk都使用,如果文件包含模式,那么gawk将用于逐行按原样放置或替换模式匹配(@Eric),并在gawk
useindex($0,string)>0
或仅index($0,string)中进行非regexp匹配
在像if
而不是0$pattern
OP这样的布尔上下文中:grep
也会“逐行”进行,因此grep
加gawk
总是比gawk
更昂贵。尽管如果你想保留原始文件和没有发现更改时的modtime,你可以使用gawk
return一个退出状态,指示它是否进行了更改。@Sundeep我认为gawk
4.1引入了-I inplace
,作为一个选项,因此如果它是一个足够新的gawk
,确实可以正常工作,那么如果我只想更改第一次出现的模式并保留其余的模式,需要做哪些更改?粘贴!f&
在前面。明白了,如果gawk-v nm2=“$2”-v nm1=“$1”!f&&index($0,nm1){f=1;$0=nm2}1;END{exit!f}'”$3“>“${3}.bak”很好,如果我只想更改第一次出现的模式并保留其余的模式,需要做些什么更改?在前面粘贴!f&&
。明白了,如果gawk-v nm2=“$2”-v 1=“$1”!f&&index($0){f=1;$0=nm2}1;结束{exit!f}''$3'>“${3}.bak”
b<*c;
./testawk "b<\*c;" "x<*y;" "aa"
gawk: warning: escape sequence `\*' treated as plain `*'
a;
b<*c;
if awk -v nm2="$2" -v nm1="$1" 'index($0,nm1){f=1; $0=nm2} 1; END{exit !f}' "$3" > "${3}.bak"
then
mv "${3}.bak" "$3"
# do stuff with modified file "$3"
else
rm -f "${3}.bak"
# do stuff with unmodified file "$3"
fi