首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在awk中使用‘`sub()’函数会导致重复的替换行为

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

Stack Overflow用户
提问于 2015-07-04 01:41:01
回答 1查看 51关注 0票数 2

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

代码语言:javascript
复制
0 0 1 * * ntpdate -s pool.ntp.org && hwclock -w

我想要实现的是用另一个ntpdate cronjob替换这一行,如下所示

代码语言:javascript
复制
0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w

如果原始的ntpdate行不存在,那么第二行将被附加到crontab文件的末尾。

因此,我用awk试了一下

代码语言:javascript
复制
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

这将导致以下(肯定是错误的)重复替换:

代码语言:javascript
复制
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脚本有什么问题?我一定是误解了什么,但我不知道在哪里。

任何帮助都是非常感谢的。谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-04 01:53:47

简洁地说,&是替换字符串中的元字符;它的意思是“您匹配的任何东西”。这就是为什么你要重复。

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

代码语言:javascript
复制
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}'

我原以为一个反斜杠就足够了,但是通过我的测试(在MacOSX10.10.4上使用BSD awkawk ),我似乎需要一个双反斜杠。我的期望与Naitreeexperience联系在一起--但我不知道为什么我需要额外的反斜杠,而他却不需要。在此期间,选择适合你的任何选项:尝试单个反斜杠,如果效果好,很好,如果不行,试试双反斜杠。

当我在一个Ubuntu14.04LTSVM上尝试这一点时,我发现awk确实是mawk 1.3.3 Nov 1996,而单反斜杠就足够了。唉哟!我怀疑BSD awk和GNU awk在这方面比mawk更接近POSIX标准,这仅仅是因为它们比mawk更新了大约十年(对我来说,BSD awkawk --version会产生awk version 20070501gawk --version会产生GNU Awk 3.1.7和2009年的最终版权日期)。

对于单个\&gawk报告:

代码语言:javascript
复制
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上。这是“添加”模式;/dev/null不包含与行匹配的内容。如果您将其保存在文件x1中,然后使用除文件名之外的相同命令行编辑x1,我得到了原始的重复行为:

代码语言:javascript
复制
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

另一个选择

正如kecomment中所建议的,一种更简单的技术可能是:

代码语言:javascript
复制
awk -v cronjob='0 0 0 * * ntpdate -s pool.ntp.org && hwclock -w' \
    '/ntpdate/ { next } { print $0 } END {print cronjob}' 

这将删除原始行,只需在输出的末尾添加新行。这对awk的所有三种变体都很有效。

YMMV --你的里程可能会不同,你被警告了。如果你不简单地回避这个问题,这些可怕的细微差别就会把你逼疯。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31216043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档