Sed 如何跳过与字符串匹配的行

Sed 如何跳过与字符串匹配的行,sed,Sed,我是sed的新手,也许有人能帮我。我正在修改一些文件,希望跳过所有带有字符串“def”或“page.”的行。在sed中如何实现这一点?AFAIK您不能(轻松地)用sed否定匹配行,但类似的方法几乎可以工作: sed '/\([^d][^e][^f][^ ]\)\|\([^p][^a][^g][^e]\)/ s/foo/bar/' FILE 在不包含def或page的行上,它将foo替换为bar,但关键是“匹配”行的长度必须至少为4个字符 更好的解决方案是使用awk,例如: awk '{ if

我是sed的新手,也许有人能帮我。我正在修改一些文件,希望跳过所有带有字符串“def”或“page.”的行。在sed中如何实现这一点?

AFAIK您不能(轻松地)用
sed否定匹配行,但类似的方法几乎可以工作:

sed '/\([^d][^e][^f][^ ]\)\|\([^p][^a][^g][^e]\)/ s/foo/bar/' FILE
在不包含
def
page
的行上,它将
foo
替换为
bar
,但关键是“匹配”行的长度必须至少为4个字符

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

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

HTH

如果我理解得很好,您希望对不同的行应用一些更改,除了一些与正则表达式匹配的行,对吗?在本例中,假设我有以下文件:

$ 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
页面中包含的行。因此,首先我们删除以
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
上述说法是正确的。有趣的是,'or'运算符与“扩展正则表达式”相关联,因此必须为“扩展正则表达式”指定-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_]*登录[A-Za-z_]*/page.&/g'new_文件
但下面的说法是有效的:

$ 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_]*登录[A-Za-z_]*/page.&/g'new_文件

这项任务更适合
grep
。@Chris同意。egrep-v'def | page'是一个开始。您想跳过这些行,不更新它,还是根本不在输出时显示它?我不确定这里问的是什么。你能提供输入和输出吗?这是sed流的一部分,还是您真的在重写
grep
?相反,在sed中很容易否定正则表达式地址!只要放一个
,例如在
/def/!s/foo/bar/
。避免修改
def
page
行的另一种方法是
-e'/def/n/page/n'
(这也避免了使用不严格可移植的扩展正则表达式)。
n
命令打印当前行并移动到下一行。这是一种很棒的方式,乔纳森!我试图传达一些避免扩展正则表达式的方法,并考虑做一些类似
/def/!{/page/!s/this/that/g;}
文件。不过,这是一个麻烦的解决方案,而您的解决方案要好得多。还有一个sed模式需要考虑:)@yoyoyo:是的,答案确实很棒,不要忘记“接受”你认为最有用的答案。当你获得更多的声誉分数时,回来投票选出你发现的任何/和所有提高你知识的答案。投票给其他人的答案不会降低你的声誉;-)祝你好运@如果您有匹配的连续行,则jonathan的建议无效。例如,如果重复第一行
这是def
,它将只跳过第一行,而在第二行进行更改。我认为你需要做
-e'/def/n/def/b/页码/n/第/b页“
@DaveGriffiths:你说得对-该死!手册上说“
[2addr]n
如果默认输出未被抑制,则将模式空间写入标准输出,并用下一行输入替换模式空间。”它不会添加我假设的“所有重要的”并开始下一个周期。修复方法是将
n
替换为
{p;d;}
,打印行并将其删除,而
d
命令具有“
[2addr]d
删除模式空间并开始下一个循环。”