当使用变量时,如何防止sed编辑包含模式第一个匹配的行?

时间:2014-03-07 13:19:03

标签: bash sed

sed代码会删除包含{$line}的所有行file.txt

sed -i "/{$pattern}/d" ./file.txt

目前,当file.txt设置为“cat”时,这会删除此示例$pattern中的所有行:

One day, the {cat} said to the {owl}, "What are you eating for breakfast, {owl}?"
The {owl} replied, "I am eating {cereal}. Would you like some, {cat}?"
"Yes, I would," replied the {cat}.
So the {cat} and the {owl} ate {cereal}.

我需要更改它,以便它不会删除包含{$pattern}的第一个找到的行,但只会删除后面行中找到的所有后续外观:

例如,假设file.txt是这样的:

One day, the {cat} said to the {owl}, "What are you eating for breakfast, {owl}?"
The {owl} replied, "I am eating {cereal}. Would you like some, {cat}?"
"Yes, I would," replied the {cat}.
So the {cat} and the {owl} ate {cereal}.

如果将$pattern设置为“cat”,则输出将如下所示,因为第1行首次出现“cat”,而其他所有后续行也都有,因此它们全部被删除:

One day, the {cat} said to the {owl}, "What are you eating for breakfast, {owl}?"

如果$pattern设置为“owl”,则输出将如下所示,因为第1行包含第一次出现的“owl”,第2行和第4行也有实例,这些实例将被删除:

One day, the {cat} said to the {owl}, "What are you eating for breakfast, {owl}?"
"Yes, I would," replied the {cat}.

如果将$pattern设置为“谷物”,则输出将如此删除第4行,因为第4行是唯一另外出现“谷物”的行。

One day, the {cat} said to the {owl}, "What are you eating for breakfast, {owl}?"
The {owl} replied, "I am eating {cereal}. Would you like some, {cat}?"
"Yes, I would," replied the {cat}.
  • 不得对文件进行排序,因为行的顺序很重要。
  • 请注意,第1行包含两个“owl”副本,但该行的第二个外观不被视为“owl”的第二个外观。

有没有办法设置sed不删除包含{$patter}首次出现的行,而只是编辑模式的所有后续出现次数?

5 个答案:

答案 0 :(得分:3)

这可能适合你(GNU sed):

sed '/{'"$var"'}/{x;//{x;d};x;h}' file

使用$var作为保留空间中的开关。

答案 1 :(得分:2)

我应该对此进行更多测试。 Potong在评论中正确地指出了

  

这将跳过每一行$并删除其他所有内容。


根据http://www.grymoire.com/Unix/Sed.html#uh-35a,您可以这样做:

sed -i '
    /{$line}/,$ {
        /{$line}/n # skip over the line that has "{$line}" on it
        d
    }
' ./file.txt

答案 2 :(得分:2)

你需要转义$d,否则它被视为shell变量并被shell扩展(可能是空字符串):

sed -i "/{$line}/{2,\$d}" ./file.txt

答案 3 :(得分:2)

替代使用awk:

$ awk "/$line/&&c++ {next} 1" ./file.txt

答案 4 :(得分:2)

使用GNU sed

sed -ne "/$line/{2,\$p}" -e "/$line/! {p}" file