首页 > 解决方案 > 如何替换一行中已知位置的未知值?

问题描述

对于我所面临的具体问题,我有一个解决方案,但它非常老套,而且根本不便携:

crontab -l > my-crontab
command='~/test.sh'
minute=1
hour=2
sed -i 's#[0-9]\+ [0-9]\+ [*]\+ [*]\+ [*]\+ '"$command"'#'"$minute"' '"$hour"' * * * '"$command"'#g' my-crontab
crontab my-crontab

例如,如果我的 crontab 中有一行读取,61 25 * * * ~/test.sh则上述解决方案将正确地将行替换为1 2 * * * ~/test.sh,我当然已经硬编码了整行的格式。

那么,更一般地说,我怎样才能找到在未知位置包含已知字符串的任何行,然后替换该行的前两列?

测试用例:my-crontab 包含许多行,其中至少有一行看起来像以下之一:

61 25 (gibberish of unknown format that contains the string ~/test.sh and more)
* 25 (gibberish of unknown format that contains the string ~/test.sh and more)
61 * (gibberish of unknown format that contains the string ~/test.sh and more)

一个可行的通用解决方案将找到任何包含字符串 ~/test.sh 的行并替换前两列:

1 2 (gibberish of unknown format that contains the string ~/test.sh and more)

我已经接受了下面使用 sed 和扩展正则表达式的答案,但我仍然有兴趣了解使用 awk 列语法的解决方案,即 $1 $2

标签: bashawksed

解决方案


在命令之前使用模式将s其限制为仅与该模式匹配的行。

然后只替换s///命令中的行首。

crontab -l > my-crontab
command='~/test.sh'
minute=1
hour=2
sed -i -r "\\#$command#s#^([^[:space:]]+[[:space:]]+[^[:space:]]+)#$minute $hour#gm" my-crontab
crontab my-crontab

推荐阅读