Bash 替换多行“&引用;用一个“&引用;
我正在使用sed清理Cisco交换机中的“show tech”或“Config”。有时在查看配置部分时,会有多行带有“!”标记。我不想删除所有的!因为这会改变配置,但我不需要只包含行的大型组!马克 简言之,与其说:Bash 替换多行“&引用;用一个“&引用;,bash,sed,replace,Bash,Sed,Replace,我正在使用sed清理Cisco交换机中的“show tech”或“Config”。有时在查看配置部分时,会有多行带有“!”标记。我不想删除所有的!因为这会改变配置,但我不需要只包含行的大型组!马克 简言之,与其说: !interface vlan200 !description ! ! ! interface vlan201 我想清理一下,以便: !interface vlan200 !description ! interface vlan201 我意识到我可以更换/卸下!使用 sed
!interface vlan200
!description
!
!
!
interface vlan201
我想清理一下,以便:
!interface vlan200
!description
!
interface vlan201
我意识到我可以更换/卸下!使用
sed 's/^!//g'
这将删除该选项!从每行的开头开始
想法
#!/usr/bin/env bash
last_line=''
while IFS= read -r line; do
[[ $line = '!' && $last_line = '!' ]] && continue
printf '%s\n' "$line"
last_line=$line
done
请参阅在运行时显示的,输出为:
!interface vlan200
!description
!
interface vlan201
救援人员:
perl -ne 'print unless /^!$/ and $previous; $previous = /^!$/' -- file
逐行读取输入-n
- 如果当前行包含单个
,则变量
设置为true代码>,其值在处理下一行时用于决定是否打印它$previous
sed -nr 'p;:loop;$!N;s/^(\!)\n\1$/\1/;tloop;D'
注意:这是sed的一个常用一行代码的次要调整(仅匹配感叹号),可在此处找到:所列代码中的另一个调整-
这源于
sed '$!N; /^\(!\)\n\1$/!P; D'
从
# delete duplicate, consecutive lines from a file (emulates "uniq").
# First line in a set of duplicate lines is kept, rest are deleted.
sed '$!N; /^\(.*\)\n\1$/!P; D'
解释
- 伙计们,看看这个。 用于引用,因为它很好,这里似乎没有任何内容与其他版本冲突
$!N
表示在不是文件末尾最后一行的行上,“向模式空间添加换行符,然后将下一行输入附加到模式空间。”这使模式空间成为“这一行和下一行”
p
打印出直到第一个换行符的图案空间部分
所以,/^\(.*\)\n\1$/!P代码>表示将第一行从开头复制到换行符,并将其用作模式的\1反向引用,这意味着匹配两个相同的连续行。如果不匹配(代码)/!
),则打印第一行。如果它们匹配,它就不会打印
D
如果模式空间不包含换行符,则开始一个正常的新循环,就像发出了d命令一样。否则,删除模式空间中直到第一个换行的文本,并使用生成的模式空间重新开始循环,而不读取新的输入行
模式末尾的D
从第一行移出,但留下附加到模式空间的第二行
所以从字面上说,它遍历文件,比较连续的行,只有当它们不相同时才打印它们
一个稍微简单一点的版本(如中所述,可能更容易阅读,尽管它仍在做几乎同样多的工作)是
这硬编码的球拍模式,至少不存储和使用的反向参考,虽然它仍然在移动它的方式通过所有的线。当我们看到一个单独的球拍时,我们可以通过堆叠线条来减少一些工作量:
sed '/^!$/N; /^!\n!$/!P; D'
p和D仍然在做他们的事情。:)
所以我们回到了我在顶部发布的模式。
希望有帮助。sed是用来做s/old/new的,就是这些
$ awk '$0!=p || $0!="!"; {p=$0}' file
!interface vlan200
!description
!
interface vlan201
以上内容将适用于任何UNIX设备上任何shell中的任何awk。它只是说如果当前行与最后一行不同,或者当前行不是代码>然后打印它。然后,它保存当前行以与下一行进行测试。这可能适用于您(GNU-sed):
打开一个两行窗口,如果第一行和第二行以开头和结尾代码>删除(不要打印)第一个。感谢您及时回复。我刚刚开始再次尝试脚本编写,虽然这可能会奏效,但有一个单行解决方案来实现这一点是很有帮助的。此外,我也不知道如何将其应用于我想要处理的文件。但我相信那是我自己的错!re:应用这个--/scriptname outfile
就可以了。或者,您可以将这些重定向直接放在完成后的(同一行)上。感谢您继续使用sed。。。。然而,perl解决方案似乎确实可以解决这个问题。感谢sed链接,我相信这将在未来有所帮助!谢谢,我也喜欢perl,但还不够用。几年后,我又开始玩bash shell脚本了。。。谢谢,这个有用!
sed '/^!$/N; /^!\n!$/!P; D'
$ awk '$0!=p || $0!="!"; {p=$0}' file
!interface vlan200
!description
!
interface vlan201
sed 'N;/^!\n!$/!P;D' file