我在带有以下内容的测试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评论)
答案 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}}。)
行;这就是你的脚本行为的原因。我们怎样才能让它按照你想要的方式行事?在某种程度上,答案取决于输出中的行的顺序是否至关重要。
如果订单无关紧要,则answer按sat完成工作。如果找到匹配的文本行,则删除它。在文件的末尾,它添加了新行。因此,无论行是否存在,输出都包含文件末尾的新所需输出。 (对于\1
文件,这应该足够了。)
如果订单确实很重要,那么你就会有更难的工作。在这种情况下,您可以使用保留空间来确定是否找到了模式。但是,如果你需要其他东西的保留空间,或者你需要更换或添加几个模式,你就不能轻易地调整它来解决这个问题(你必须对它更加聪明)。
如果行的顺序无关紧要,请不要使用此项。
示例:文件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
)表明您需要至少一行输入才能正常工作;它不会从空文件引导。
可能有一种更简单的方法来处理这个问题。我还没弄清楚它是什么。
这基本上是answer到sat,操作顺序颠倒了。当要删除的行是文件中的最后一行时,它可以工作:
/dev/null
答案 1 :(得分:0)
您可以尝试此sed
,
sed '\#file example/example.xml#{d}; $a bar' yourfile