如何查找和替换,跳过包含特定字符的行?

时间:2014-08-18 06:57:44

标签: bash sed

我正在使用sed来查找和替换文件中模式的第一个外观:

sed -i "0,\#pattern#s##replacement#" ./file.txt

如何告诉它跳过包含{的任何行。以下是输入示例:

This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the pattern, and not the character, so it will be changed.

以下是示例输出:

This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the replacement, and not the character, so it will be changed.
  • 整个文件只进行了一次更改。
  • 如果带有该模式的每一行都包含{,则不会对该文件进行任何更改。

如何使用sed查找和替换项目的第一个外观,但跳过包含其他模式的任何行,在本例中为{

5 个答案:

答案 0 :(得分:2)

您只需添加一个小修改:

sed -i -e '/{/!s/pattern/replacement/' file

如果行匹配s,它会跳过更改任何内容(跳过/{/)。 !否定它并允许s

这是同义词:

sed -i -e '/{/b; s/pattern/replacement/' file

b使其跳过(跳到结束)。

测试:

# sed '/{/!s/pattern/replacement/' file
This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the replacement, and not the character, so it will be changed.

如果您需要替换多个模式,请添加g

sed -i -e '/{/!s/pattern/replacement/g' file

更新

使用awk

awk '!/{/ && !x { x = sub(/pattern/, "replacement") } { a[NR] = $0 }
     END { for (i = 1; i <= NR; ++i) print a[i] }' file

输入:

This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the pattern, and not the character, so it will be changed.
This line has the pattern, and not the character, so it will be changed.

输出:

This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the replacement, and not the character, so it will be changed.
This line has the pattern, and not the character, so it will be changed.

直接对文件进行更改:

awk '!/{/ && !x { x = sub(/pattern/, "replacement") } { a[NR] = $0 }
     END { for (i = 1; i <= NR; ++i) print a[i] > FILENAME }' file

使用gsub代替sub替换第一条匹配线上的多个匹配。

答案 1 :(得分:2)

这可能适合你(GNU sed):

sed '/{/b;/pattern/{s//replacement/;:a;n;ba}' file

在匹配第一个模式时跳过包含{的任何行,将其替换为替换,然后将剩余的行打印到文件结尾。

答案 2 :(得分:1)

您可以尝试awk

awk '!/{/ {sub(/pattern/,"replacement")}1' file
This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the replacement, and not the character, so it will be changed.

这会将pattern替换为replacement,而不是{


更改文件(模拟sed -i

awk '!/{/ {sub(/pattern/,"replacement")}1' file > tmp && mv tmp file

答案 3 :(得分:1)

使用perl会更简单:

perl -pe 's/pattern/replacement/ unless(/\{/)' your_file

到位替换:

perl -pi -e 's/pattern/replacement/ unless(/\{/)' your_file

答案 4 :(得分:1)

仅针对此文件的一个替换修改Jotne解决方案:

This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the pattern, and not the character, but another pattern.
This line has the pattern, and not the character, but is the second line.

awk 'BEGIN {b = 0} !/{/ && !b { b=sub(/pattern/,"replacement");}1' file

并给出

This line does not have the item, so it is skipped.
This line has the pattern, but also has {, so it is skipped too.
This line has the replacement, and not the character, but another pattern.
This line has the pattern, and not the character, but is the second line.

Gnu awk也有一个就位选项:

gawk -i inplace 'BEGIN {b = 0} !/{/ && !b { b=sub(/pattern/,"replacement");}1' file