我是sed的新手,所以也许有人可以帮助我。我正在修改一些文件,并希望跳过所有包含字符串“def”或“page”的行。在他们。我怎么在sed中这样做?
答案 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
,但忽略def
或page
所包含的行。首先,我们删除以def
或page
开头的行:
/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
它在不包含foo
或bar
的行上用def
替换page
但是捕获的是“匹配”行必须至少为4个字符长。
更好的解决方案是使用awk
,例如:
awk '{ if ($0 !~ /def|page/) { print gensub("foo","bar","g") } else { print } }' FILE
HTH