Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.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
在awk中使用'sub()'函数会导致重复的替换行为_Awk - Fatal编程技术网

在awk中使用'sub()'函数会导致重复的替换行为

在awk中使用'sub()'函数会导致重复的替换行为,awk,Awk,假设我有一个/etc/crontab文件示例: 0 0 1 * * ntpdate -s pool.ntp.org && hwclock -w 我想要实现的是用另一个ntpdatecronjob替换这一行,如下所示 0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w 如果原始的ntpdate行不存在,那么第二行只会追加到crontab文件的末尾 因此,我用awk进行了尝试: awk -v cronjob='0 0 0

假设我有一个
/etc/crontab
文件示例:

0 0 1 * * ntpdate -s pool.ntp.org && hwclock -w
我想要实现的是用另一个
ntpdate
cronjob替换这一行,如下所示

0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w
如果原始的
ntpdate
行不存在,那么第二行只会追加到
crontab
文件的末尾

因此,我用
awk
进行了尝试:

awk -v cronjob='0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w' '/ntpdate/ { sub(/^.*$/,cronjob,$0);found=1; }; { print $0 }; END {if(!found) print cronjob}' /etc/crontab
这会导致以下(肯定是错误的)重复更换:

0 0 0 * * ntpdate -s pool.ntp.org 0 0 1 * * ntpdate -s pool.ntp.org && hwclock -w0 0 1 * * ntpdate -s pool.ntp.org && hwclock -w hwclock -w
我的
awk
脚本有什么问题?我一定是误解了什么,但我不知道在哪里


感谢您的帮助。谢谢。

简而言之,
&
是替换字符串中的元字符;意思是“你配什么就配什么”。这就是为什么你会被重复

下一个问题是“如何避免”。答案似乎是两对反斜杠:

awk -v cronjob='0 0 0 * * ntpdate -s pool.ntp.org \\&\\& hwclock -w' \
    '/ntpdate/ { sub(/^.*$/,cronjob,$0); found=1; } { print $0 }
     END {if(!found) print cronjob}'
我原以为一个反斜杠就足够了,但在我的测试中(在Mac OS X 10.10.4上同时使用BSD
awk
和GNU
awk
),我似乎需要一个双反斜杠。我的期望与s一致,但我不确定为什么我需要额外的反斜杠,而他没有。在此期间,选择对您有效的选项:尝试单反斜杠,如果有效,很好,如果无效,则尝试双反斜杠

当我在Ubuntu14.04 LTS虚拟机上尝试这一点时,我发现
awk
确实是
mawk 1.3.3,1996年11月
,单反斜杠就足够了。哎哟我怀疑BSD
awk
和GNU
awk
在这方面比
mawk
更接近POSIX标准,哪怕只是因为它们更新了十年左右(对我来说,
awk--version
对于BSD
awk
产生了
awk version 20070501
,而
gawk--version
产生了
GNU awk 3.1.7
,版权终止日期为2009年)

使用单个的
\&
gawk
报告:

gawk -v cronjob='0 0 0 * * ntpdate -s pool.ntp.org \&\& hwclock -w' \
     '/ntpdate/ { sub(/^.*$/,cronjob,$0);found=1; } { print $0 }
      END {if(!found) print cronjob}' /dev/null
gawk: warning: escape sequence `\&' treated as plain `&'
0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w
注意这个警告。它出现在Ubuntu和MacOSX上。 这是“添加”模式;
/dev/null
不包含该行的匹配项。如果您将其保存在文件
x1
中,然后使用除文件名之外的相同命令行编辑
x1
,则我得到了原始的重复行为:

0 0 0 * * ntpdate -s pool.ntp.org 0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w hwclock -w
或者 如a中所示,一种更简单的技术可能是:

awk -v cronjob='0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w' \
    '/ntpdate/ { next } { print $0 } END {print cronjob}' 
这将删除原始行,并在输出的末尾添加新行。这在
awk
的所有三个变体中都能正常工作


YMMV-你的里程数可能会有所不同;你被警告过。如果你不简单地回避问题,这些可怕的细微差别会让你发疯。

&
是替换字符串中的元字符;它意味着“你匹配的任何东西”。@JonathanLeffler哦,是的,我明白了……我不知道de>&是
cronjob
变量的一部分造成了混乱…谢谢。你介意把你的评论用词组表达成一个答案,这样我就可以接受它吗?也可以…只是解决问题…我刚刚逃过了
&
像这样的
\&
,它成功了…你可以使用
awk'/ntpdate/{$3=0}/etc/crontab'
在这种情况下。对于更一般的情况,您只需删除匹配的行并附加新的行。这样,您可以在避免替换和找到
变量的同时获得相同的效果。