在 awk 的最新版本中,有一个inplace
选项可用于执行类似于sed
-i 选项的就地操作。但是我无法让它与print
声明一起工作。让我们看看我的例子。文件test的内容为:
11 aa
22 bb
root@localhost:~# cat test
11 aa
22 bb
如果我不使用-i inplace
,我可以在控制台中得到我想要的结果。
root@localhost:~# awk 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' test
begin
111aa
22 bb
end
当我添加时-i inplace
,这就是我得到的。
root@localhost:~# awk -i inplace 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' test
begin
end
root@localhost:~# cat test
111aa
22 bb
root@localhost:~#
如何改进我的代码并得到我想要的东西?
更新
我的 awk 版本是4.1.1
.
root@localhost:~# awk --version
GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2-p3, GNU MP 6.0.0)
Copyright (C) 1989, 1991-2014 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
root@localhost:~#
更新2
root@localhost:~# awk --version
GNU Awk 4.1.2, API: 1.1
Copyright (C) 1989, 1991-2015 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
root@localhost:~# cat file
11 aa
22 bb
root@localhost:~# awk 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' file
begin
111aa
22 bb
end
root@localhost:~# awk -i inplace 'BEGIN{print "begin"} $1=="11"{print "111" $2; next} 1; END{print "end"}' file
begin
end
root@localhost:~# cat file
111aa
22 bb
root@localhost:~#
答案1
我认为您需要使用 BEGINFILE 而不是 BEGIN,使用 ENDFILE 而不是 END 作为开始和结束打印到文件中。
至少这在 cygwin 上有效。
Rob@Rob-PC /cygdrive/c/tmp
$ awk --version
GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2, GNU MP 6.0.0)
Copyright (C) 1989, 1991-2014 Free Software Foundation.
Rob@Rob-PC /cygdrive/c/tmp
$ echo "11 aa
22 bb" > test
Rob@Rob-PC /cygdrive/c/tmp
$ awk -i inplace 'BEGINFILE{print "begin"} $1=="11"{print "111" $2; next} 1; ENDFILE{print "end" >> "test"}' test
Rob@Rob-PC /cygdrive/c/tmp
$ cat test
begin
111aa
22 bb
end
答案2
BEGIN
和循环END
在处理文件之前和完全处理文件之后运行。只有-i inplace
在处理文件时才有意义。如果不检查源代码,我无法确定,但因此,BEGIN
andEND
在这里不起作用似乎是合理的。
正如已经建议的,这就是BEGINFILE
和ENDFILE
的用途。如果这些在您的设置中不起作用,您将不得不使用解决方法。虽然匹配第一行很容易 ( if(NR==1){print "begin"}
),但匹配最后一行则有点棘手。您可以使用的一些技巧是:
使用另一个工具添加开始线和结束线:
perl -i -007ne 'print "begin\n${_}end\n"' file && awk -i inplace '$1=="11"{print "111" $2; next}1;' file
或者
printf "begin\n%s\nend" "$(cat file)"
用于
awk
“开始”并稍后添加“结束”:awk -i inplace 'NR==1{print "begin"}$1=="11"{print "111" $2; next}1;' file && echo "end" >> file
使用可以理解的工具来完成整个事情
eof
。 Perl 的-a
switch 使它的行为类似于awk
:它将空格上的字段分割到@F
数组中。就像 一样awk
,该-F
开关允许您设置字段分隔符。开关-i
就地编辑文件:perl -i -lane '$.==1 && print "begin"; eof && print "end"; if($F[0]=="11"){print "111$F[0] $F[1]"; next} print;' file