假设我有这个/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
(,我似乎需要一个双反斜杠。我的期望和奈特里的经历有关——但我不确定为什么我需要额外的反斜杠,而他没有。在此期间,选择对您有效的选项:尝试单反斜杠,如果有效,那就太好了,如果无效,那就尝试双反斜杠。
当我在Ubuntu 14.04 LTS虚拟机上尝试此操作时,我发现awk
确实是mawk 1.3.3 Nov 1996
,并且单个反斜杠就足够了。哎哟我的怀疑是,BSD awk
和GNU awk
在这方面比mawk
更接近POSIX标准,哪怕只是因为它们更新了十年左右(对我来说,BSD的awk
的awk --version
产生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和Mac OS X上。这就是"加法"模式;/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
或者
正如pii_ke在评论中所建议的,一种更简单的技术可能是:
awk -v cronjob='0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w'
'/ntpdate/ { next } { print $0 } END {print cronjob}'
这将删除原来的行,并简单地在输出的末尾添加新的行。这对awk
的所有三种变体都起到了合理的作用。
YMMV-您的里程数可能有所不同;你被警告了。如果你不简单地回避这个问题,这些可怕的细微差异会让你发疯。