Sed 如何跳过与字符串匹配的行
我是sed的新手,也许有人能帮我。我正在修改一些文件,希望跳过所有带有字符串“def”或“page.”的行。在sed中如何实现这一点?AFAIK您不能(轻松地)用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否定匹配行,但类似的方法几乎可以工作:
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中很容易否定正则表达式地址!只要放一个正则表达式前面的code>,例如在/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
删除模式空间并开始下一个循环。”