【问题标题】:How can I replace unknown values in known positions in a line?如何替换一行中已知位置的未知值?
【发布时间】:2021-02-05 04:57:46
【问题描述】:

对于我遇到的特定问题,我有一个解决方案,但它很老套,根本不便携:

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

【问题讨论】:

  • 请发布具有相关预期输出的可测试样本,将它们编辑到您的帖子中,不要将它们作为 cmets 或图像发布。谢谢。
  • 我会在命令后添加# autofoobar 以使其易于识别,然后将其过滤掉并重新添加:{ crontab -l | grep -v autofoobar; echo "$minute $hour * * * $command # autofoobar"; } | crontab -

标签: bash awk sed


【解决方案1】:

在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

【讨论】:

    【解决方案2】:

    使用 awk:

    awk -v min="$minute" -v hrs="$hour" -v scr="$command" '$6 == scr { $1=min;$2=hrs }1' my-crontab > my-crontab.tmp && mv -f my-crontab.tmp my-crontab
    

    将分钟和小时以及命令变量作为 min amd hrs 和 scr 传递给 awk。如果第 6 个空格分隔字段与 scr 相同,则将第一个字段设置为 min,将第二个字段设置为 hrs。打印所有行以及对临时文件的修改并将主文件替换为临时文件。

    【讨论】:

    • 感谢您的快速答复。我不知道我正在搜索的字符串将在第 6 列(或任何特定列)中,并且我已经编辑了问题以反映这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多