![sed + 删除第一个匹配或第二个匹配上的字符](https://linux22.com/image/120720/sed%20%2B%20%E5%88%A0%E9%99%A4%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8C%B9%E9%85%8D%E6%88%96%E7%AC%AC%E4%BA%8C%E4%B8%AA%E5%8C%B9%E9%85%8D%E4%B8%8A%E7%9A%84%E5%AD%97%E7%AC%A6.png)
以下 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