sed + 删除第一个匹配或第二个匹配上的字符

sed + 删除第一个匹配或第二个匹配上的字符

以下 sed 语法删除“Require all granted”行中的“#”

   sed 's/#\([[:space:]]*Require all granted\)/ \1/' graphite-web.conf

   #<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
        Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

如何更改 sed 语法以删除第一个匹配项上的“#”?或者第二场比赛?

预期输出:

   #<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
        Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

或者

   #<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
   #    Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

答案1

改用awk

$ cat ip.txt 
   #    Allow from All
   #    Require all granted
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

$ awk '/#[[:space:]]*Require all granted/ && ++c==1{sub("#", " ")} 1' ip.txt
   #    Allow from All
        Require all granted
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

$ awk '/#[[:space:]]*Require all granted/ && ++c==2{sub("#", " ")} 1' ip.txt
   #    Allow from All
   #    Require all granted
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

$ awk '/#[[:space:]]*Require all granted/ && ++c>1{sub("#", " ")} 1' ip.txt
   #    Allow from All
   #    Require all granted
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
        Require all granted
   #    Order Deny

也可以看看awk 将修改保存到位


或者,使用perl

$ # for inplace editing, use perl -i -pe
$ perl -pe 's/#/ / if /#\s*Require all granted/ && ++$c==1' ip.txt
   #    Allow from All
        Require all granted
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Require all granted
   #    Order Deny

答案2

或者sed方法:

sed ':a;N;$!ba;s/#\([[:space:]]*Require all granted\)/ \1/2' graphite-web.conf

如果输入文件包含:

#<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
   #    Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
   #    Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

输出将是:

#<IfModule mod_authz_core.c>
   #    # Apache 2.4
   #    Require local
   #    Order Allow,Deny
   #    Allow from All
   #    Require all granted
   #</IfModule>
   #<IfModule !mod_authz_core.c>
   #    # Apache 2.2
        Require all granted
   #    Order Allow,Deny
   #    Deny from all
   #    Allow from All
   #    Allow from ::1
   #</IfModule>

此模式:a;N;$!ba;在文件结束之前读取所有行(如 while 循环),并在 eof 到达后执行s///2第二次出现的替换。

您可能读过的 sed 标签的最佳解释:a;$!N; 是什么意思?在 sed 命令中?

并阅读类似的主题如何使用 sed 替换第 n 次出现的字符串

答案3

塞德旨在在流上工作。完成你想要的事情的一个简单方法是使用ed

ed -s graphite-web.conf <<<$'/Require all/s/#/ /\nw'

更新:我可以详细说明ed但是这个ed更详细地解释及其广泛的用法。

我对这一行的解释是:

-s意思是相当。不要显示我们改变了什么。

然后我们使用herestring<<<并应用ANSI C$''形式的引用,其中反斜杠字符组合被扩展。\nw意味着我们添加一个新行并写入文件。

答案4

这是一个ex版本...将 shell 变量设置x为一个数字,指示要更改的出现次数(例如,使用x=2该命令将修改该模式的第二次出现)...

这个就地更新输入文件:

ex +'/#\(\s*Require all granted\)/|1' +"norm ${x}n" +'s// \1/|wq' file 

这是一个管道变体,它不修改文件,但将修改后的版本打印到标准输出

cat file | ex +'/#\(\s*Require all granted\)/|1' +"norm ${x}n" +'s// \1/' +'%p|q!' /dev/stdin

细节:

当它不以交互方式运行时,ex本质上是一个以命令行模式为中心的批处理版本的vim.所以很多内容对于vim用户来说应该是熟悉的......

  • /#\(\s*Require all granted\)/|1- 搜索模式,然后转到第 1 行“重置”
  • norm ${x}n- 转到n模式x次数的 ext 出现位置
  • s// \1/|wq- 仅在当前行进行替换然后 write-quit

相关内容