如何跳过匹配字符串的行

时间:2011-07-13 19:59:06

标签: sed

我是sed的新手,所以也许有人可以帮助我。我正在修改一些文件,并希望跳过所有包含字符串“def”或“page”的行。在他们。我怎么在sed中这样做?

2 个答案:

答案 0 :(得分:18)

如果我理解得很好,你想对除了匹配正则表达式的一些线以外的各种线应用一些更改,对吧?在这种情况下,让我们假设我有以下文件:

$ cat file
this is a def
this has no d e f
this is a page by the way
but this is no p a g e as we know ito

我们希望将所有this替换为that,但忽略defpage所包含的行。首先,我们删除以defpage开头的行:

/def/d;/page/d;

然后我们照常应用我们的操作:

s/this/that/g

结果是:

$ sed '/def/d;/page/d;s/this/that/g' file
that has no d e f
but that is no p a g e as we know ito

但如果通过“跳过”表示“不执行我的操作”,则只需取消地址:

$ sed -E '/(def|page)/!s/this/that/g' file
this is a def
that has no d e f
this is a page by the way
but that is no p a g e as we know ito

以上陈述正确无误。有趣的是,'或'运算符与“扩展正则表达式”相关联。因此,您必须为“扩展正则表达式”指定-E,因为默认情况下,sed仅使用“基本正则表达式”。

例如,以下语句不起作用:

$ sed -e '/(def|page)/!s/[A-Za-z_]*login[A-Za-z_]*/page.&/g' < file > new_file

但下面的陈述有效:

$ sed -E '/(def|page)/!s/[A-Za-z_]*login[A-Za-z_]*/page.&/g' < file > new_file

答案 1 :(得分:1)

AFAIK你不能(轻易地)否定与sed匹配的行,但是类似的东西几乎可以工作:

sed '/\([^d][^e][^f][^ ]\)\|\([^p][^a][^g][^e]\)/ s/foo/bar/' FILE

它在不包含foobar的行上用def替换page但是捕获的是“匹配”行必须至少为4个字符长。

更好的解决方案是使用awk,例如:

awk '{ if ($0 !~ /def|page/) { print gensub("foo","bar","g") } else { print } }' FILE

HTH