Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash gawk和grep使用相同的模式,但需要对逃逸序列进行不同的处理_Bash_Shell_Awk_Grep_Gawk - Fatal编程技术网

Bash gawk和grep使用相同的模式,但需要对逃逸序列进行不同的处理

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"

我有一个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".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
for
grep
告诉它把参数当作固定字符串,而不是模式,也可以使用
-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
use
index($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