使用sed编辑crontab

u53*_*891 3 unix bash shell sed crontab

我正在编写sed命令,该命令应取消注释crontab中的条目。有一个更好的方法吗?想到的第一个选项是sed。

例:

crontab -l

# 5 * * * 3 bash test.sh
Run Code Online (Sandbox Code Playgroud)

sed命令应取消注释该条目。这就是我现在所拥有的。

sed "s#\# 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"
Run Code Online (Sandbox Code Playgroud)

显然,此sed命令不会执行此任务。

ps:sed命令最终将进入脚本。

gho*_*oti 5

Sed非常适合匹配特定的正则表达式并以某些方式处理文本,但是在我看来这并不是其中之一。尽管您可以使用sed执行此任务,但结果可能过于复杂和脆弱。

您最初的尝试是:

sed "s#\# 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"
Run Code Online (Sandbox Code Playgroud)

之所以失败,是因为该*字符在您的正则表达式中是一个特殊字符,并且被翻译为“零个或多个先前原子”(在这种情况下为空格)。严格来说,您可以通过转义正则表达式中的星号来使此sed脚本起作用(替换模式中不需要)。

但这仅有助于此特定模式。如果您的一位同事决定在小时后的6分钟而不是5分钟后运行此脚本,以避免与另一个脚本发生冲突,该怎么办?还是在注释字符后面有空格?突然,您的sed替换失败。

要取消注释该脚本的每个注释,请使用:

crontab -l | sed '/# *\([^ ][^ ]*  *\)\{5\}[^ ]*test\.sh/s/^# *//' | crontab -
Run Code Online (Sandbox Code Playgroud)

如果您使用的是更现代的sed,则可以将此BRE替换为稍微短一点的ERE:

crontab -l | sed -E '/# *([^ ]+  *){5}[^ ]*test\.sh/s/^# *//' | crontab -
Run Code Online (Sandbox Code Playgroud)

这将获得的输出crontab -l,显然是您完整的crontab,使用sed对其进行操作,然后使用来基于其输出写入新的crontab crontab -。sed脚本匹配搜索与看起来像有效crontab的行匹配的行(以避免实际的注释只提及您的脚本),然后进行简单替换以在开始时仅删除注释字符。匹配的模式如下所示:

  • # * -匹配后跟零个或多个空格的注释字符
  • ([^ ]+ +){5} -五个非空格字符串,后跟空格
  • [^ ]* -任意数量的非空格字符,导致:
  • test\.sh -您的脚本。

但是请注意,这不符合所有有效的crontab次,其中可能包括像标签@reboot@weekly@midnight等退房man 5 crontab的细节。


awk可能需要使用非sed替代方法。以下awk解决方案对我来说更有意义:

crontab -l | awk -v script="test.sh" '
  { field=6 }
  /^# / { field++ }
  index($field,script) { sub(/^#/,"") }
  1' \
| crontab -
Run Code Online (Sandbox Code Playgroud)

虽然时间更长一点,但我发现它更易于阅读和理解。