在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上同时使用BSDawk
和GNUawk
),我似乎需要一个双反斜杠。我的期望与s一致,但我不确定为什么我需要额外的反斜杠,而他没有。在此期间,选择对您有效的选项:尝试单反斜杠,如果有效,很好,如果无效,则尝试双反斜杠
当我在Ubuntu14.04 LTS虚拟机上尝试这一点时,我发现awk
确实是mawk 1.3.3,1996年11月
,单反斜杠就足够了。哎哟我怀疑BSDawk
和GNUawk
在这方面比mawk
更接近POSIX标准,哪怕只是因为它们更新了十年左右(对我来说,awk--version
对于BSDawk
产生了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'
在这种情况下。对于更一般的情况,您只需删除匹配的行并附加新的行。这样,您可以在避免替换和找到变量的同时获得相同的效果。