如何正确执行此修改或使用sed插入行?

时间:2014-05-30 14:05:51

标签: sed

我在带有以下内容的测试crontab文件上运行它:

00 01 * * * foo --file example/example.xml --bla
00 02 * * * foo --file abc/abc.xml --bla

我正在尝试将第一行(如果存在)替换为其他内容,例如' bar',或者如果根本无法找到它,则插入条形线:

sed -e '@\(.*file example/example.xml .*\)@bar@' -e t -e 's@^@bar@' file

我希望上面的内容尝试用bar替换匹配的示例行,如果它没有找到它来插入一个条形线。然而,当我使用上面的操作时,我得到了这个输出:

bar
bar00 02 * * * foo --file abc/abc.xml --bla

所以它执行了替换,但不知何故t跳转到结尾没有发生,它还在下一行插入bar。出了什么问题?

下面给出的命令似乎有效,但是如果我运行两次并且我不确定原因,则无法追加:

cat file
1 bin/appple #apple
2 bin/orange #orange
cat file | sed -e '\@.* #apple@{d}; $a 1 bin/apple #apple'
2 bin/orange #orange
1 bin/apple #apple
cat file | sed -e '\@.* #apple@{d}; $a 1 bin/apple #apple' | sed -e '\@.* #apple@{d}; $a 1 bin/apple #apple'
2 bin/orange #orange

上面的表现就像我想要的前两次一样,但是最后一个命令只是删除了该行并且没有追加它。那为什么会这样? (顺便说一句,我把#改为了@,因为我在那里使用了#,你可以想象一下crontab评论)

2 个答案:

答案 0 :(得分:2)

修正拼写错误(缺少s)后,命令:

sed -e 's@\(.*file example/example.xml .*\)@bar@' -e t -e 's@^@bar@' file

按照您的要求工作;我认为你误解了t的范围。该测试依次适用于每一行输入,而不是整个脚本。所以,剧本说:

  • 如果该行包含file example/example.xml,请将其替换为bar
  • 如果替换完成,请跳到脚本的末尾(对于当前输入行)。
  • 将行的开头替换为bar(第二条数据线会发生这种情况,因为它与file example/example.xml不匹配。)

(我顺便提一下,当替换为\(时,不需要\)bar,但这可能只是您使用{更复杂的替代品中的遗留物{ {1}}。)

行;这就是你的脚本行为的原因。我们怎样才能让它按照你想要的方式行事?在某种程度上,答案取决于输出中的行的顺序是否至关重要。

  1. 如果订单无关紧要,则answersat完成工作。如果找到匹配的文本行,则删除它。在文件的末尾,它添加了新行。因此,无论行是否存在,输出都包含文件末尾的新所需输出。 (对于\1文件,这应该足够了。)

  2. 如果订单确实很重要,那么你就会有更难的工作。在这种情况下,您可以使用保留空间来确定是否找到了模式。但是,如果你需要其他东西的保留空间,或者你需要更换或添加几个模式,你就不能轻易地调整它来解决这个问题(你必须对它更加聪明)。

  3. 如果订单重要

    如果行的顺序无关紧要,请不要使用此项。

    示例:文件crontab包含:

    sed.script

    此脚本有两组操作。第一组,当线匹配/.*file example\/example.xml.*/ { h s//bar/ } $ { p x s/./X/ t end s/.*/bar/ q :end d } 时很简单;它将行复制到保留空间(因此保留空间不再为空),然后执行替换操作。

    第二组要复杂得多;它在脚本结束时运行。首先,它打印当前行。如果该行已被第一个块修复(因此file example/example.xml出现在最后一行),则会打印该行的修改形式。然后它交换保持和模式空间。它进行了试验替代(file example/example.xml)。如果进行了替换,s/./X/命令将跳转到标签t,这意味着该行不为空,这意味着保留空间已填充,因此模式已被替换(至少)一次之前。如果end没有跳转,则看不到匹配模式,因此代码用t替换当前行(替换文本)并退出(打印最后一行并放弃脚本) 。标签bar后跟end,删除当前行并“移至下一个周期”,但d匹配生效时没有下一个周期,所以没有剩下任何内容打印。

    示例运行:

    $

    第一个$ cat file 00 01 * * * foo --file example/example.xml --bla 00 02 * * * foo --file abc/abc.xml --bla $ sed -f sed.script file bar 00 02 * * * foo --file abc/abc.xml --bla $ sed -f sed.script file | sed -f sed.script bar 00 02 * * * foo --file abc/abc.xml --bla bar $ sed -f sed.script /dev/null $ 表示sed行已就地替换。第二个example/example.xml表示当缺少sed行时,会在最后添加example/example.xml。最后一个示例(bar)表明您需要至少一行输入才能正常工作;它不会从空文件引导。

    可能有一种更简单的方法来处理这个问题。我还没弄清楚它是什么。

    如果订单无关紧要

    这基本上是answersat,操作顺序颠倒了。当要删除的行是文件中的最后一行时,它可以工作:

    /dev/null

答案 1 :(得分:0)

您可以尝试此sed

sed '\#file example/example.xml#{d}; $a bar' yourfile