使用 sed 编辑 crontab [英] Use sed to edit crontab

查看:86
本文介绍了使用 sed 编辑 crontab的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a sed command that should uncomment an entry in crontab. Is there a better way to do this? The first option that comes to mind is sed.

示例:

crontab -l

# 5 * * * 3 bash test.sh

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

The sed command should uncomment this entry. This is what I have now.

sed "s## 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"

显然这个 sed 命令不能完成任务.

Obviously this sed command doesn't do the task.

ps:sed 命令最终会进入脚本.

ps:the sed command will eventually make its way into a script.

推荐答案

Sed 非常适合匹配特定的正则表达式和以某些方式操作文本,但在我看来这不是其中之一.虽然您可以将 sed 用于此任务,但结果可能过于复杂和脆弱.

Sed is great for matching specific regular expressions and manipulating text in certain ways, but this doesn't seem to me to be one of them. While you can use sed for this task, the result is perhaps overly complex and fragile.

您最初的尝试是:

sed "s## 5 * * * 3 bash test.sh#5 * * * 3 bash test.sh#"

这会失败,因为 * 字符是正则表达式中的特殊字符,被翻译为前一个原子的零个或多个"(在本例中为空格).严格来说,您可以通过转义正则表达式中的星号(在您的替换模式中不需要)来让这个 sed 脚本工作.

This fails because the * character is a special character within your regular expression, and is translated as "zero or more of the previous atom" (in this case, a space). Strictly speaking, you may get this sed script to work by escaping the asterisks in your regex (not required in your replacement pattern).

但这仅对这种特定模式有帮助.如果您的一位同事决定在整点后 6 分钟而不是 5 分钟运行此脚本,以避免与另一个脚本发生冲突,该怎么办?或者评论字符后面有一个空格?突然你的 sed 替换失败了.

But this only helps for this specific pattern. What if one of your co-workers decides to run this script at 6 minutes after the hour instead of 5, in order to avoid conflict with another script? Or there's a space after the comment character? Suddenly your sed substitution fails.

要取消注释有问题的脚本的每个注释出现,您可以使用:

To uncomment out every commented occurrence of the script in question, you might use:

crontab -l | sed '/# *([^ ][^ ]*  *){5}[^ ]*test.sh/s/^# *//' | crontab -

如果您使用的是 更现代的 sed,您可以用稍短的 ERE 替换此 BRE:

If you're using a more modern sed, you could replace this BRE with a slightly shorter ERE:

crontab -l | sed -E '/# *([^ ]+  *){5}[^ ]*test.sh/s/^# *//' | crontab -

这需要crontab -l 的输出,这显然是你完整的crontab,用sed 操作它,然后使用crontab -.sed 脚本匹配搜索与有效 crontab 匹配的行(以避免仅提及您的脚本的实际注释),然后执行简单的替换以仅删除开头的注释字符.匹配的模式如下所示:

This takes the output of crontab -l, which is obviously your complete crontab, manipulates it with sed, and then writes a new crontab based on its output using crontab -. The sed script matches searches for lines matching what looks like a valid crontab (to avoid actual comments that simply mention your script), then does a simple substitution to remove only the comment character at the start. The matched pattern breaks out like this:

  • # * - 匹配后跟零个或多个空格的注释字符
  • ([^ ]+ +){5} - 五个非空格字符串,后跟空格
  • [^ ]* - 任意数量的非空格字符,导致:
  • test.sh - 你的脚本.
  • # * - Matches the comment character followed by zero or more spaces
  • ([^ ]+ +){5} - five non-space strings, followed by spaces
  • [^ ]* - Any number of non-space characters, which lead up to:
  • test.sh - your script.

但是请注意,这与所有有效的 crontab 时间不匹配,其中可能包括诸如 @reboot@weekly@midnight 等.查看man 5 crontab 了解详情.

Note, however, that this doesn't match all valid crontab times, which might include tags like @reboot, @weekly, @midnight, etc. Check out man 5 crontab for details.

awk 这样的非 sed 替代品可能是合适的.以下 awk 解决方案对我来说更有意义:

A non-sed alternative like awk might be in order. The following awk solution makes more sense to me:

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

虽然有点长,但我觉得它更容易阅读和理解.

While it's just a little longer, I find it easier to read and understand.

这篇关于使用 sed 编辑 crontab的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆