替换多行“!”一个“!”

时间:2018-07-27 16:00:28

标签: bash sed replace

我正在使用sed清除Cisco交换机中的“ show tech”或“ configs”。有时在查看配置部分时,多行带有“!”分数。我不想删除所有!因为这会改变配置,但是我不需要只包含!行的大型组。标记。

因此,简而言之,不是:


for (newSkill of transaction.newSkills) {

我想清理一下:

!interface vlan200
!description 
!
!
!
interface vlan201

我知道我可以更换/拆卸!使用

!interface vlan200
!description
!
interface vlan201

这将删除!从每一行的开头开始。

有想法吗?

6 个答案:

答案 0 :(得分:3)

pattern link列出的gregory中的另一项调整-

sed '/^!$/N; /^!\n!$/!P; D'

这是基于

的基本模式
 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'

解释

  • 伙计们,请检查一下我。 很好,使用GNU's manual进行引用,这里似乎与其他版本没有冲突。
  

N

     

在模式空间中添加换行符,然后将输入的下一行追加到模式空间中。如果没有更多输入,则sed退出而不处理任何其他命令。

  

附加!地址说明末尾的字符(在命令字母之前)会否定匹配的含义。也就是说,如果!字符位于地址或地址范围之后,则只会选择与地址不匹配的行。

$是文件的末尾,因此$!N表示不在文件末尾的行上,“在模式空间中添加换行符,然后将输入的下一行附加到模式空间。”这使模式空间成为“这一行和下一行”。

  

P

     

打印出图案空间的一部分,直到第一行。

因此,/^\(.*\)\n\1$/!P;意味着将第一行从开头复制到换行符,并将其用作\ 1 backref作为模式的一部分,这意味着匹配2条相同的连续行。如果不匹配(/!),则打印第一行。如果它们匹配匹配,则不会打印。

  

D

     

如果模式空间不包含换行符,请像发出d命令一样开始正常的新循环。否则,删除模式空间中的文本,直到第一行换行,然后使用结果模式空间重新开始循环,而无需读取新的输入行。

模式结尾处的D正在移出第一行,但将第二行附加到模式空间中。

因此,从字面上看,它会遍历文件,比较连续的行,并仅在不相同的行时打印它们。

一个稍微的简单版本(例如,虽然它仍在进行几乎相同的工作,但也许更容易阅读)

 sed '$!N; /^!\n!$/!P; D'

这会硬编码球形模式,尽管它仍在所有行中移动,但至少不存储和使用后向引用。当看到一个孤单的球棒时,我们可以通过仅堆叠行来减少这项工作:

sed '/^!$/N; /^!\n!$/!P; D'

P和D仍然在做自己的事情。 :)

因此,我们回到了我在顶部发布的模式。 希望有帮助。

答案 1 :(得分:1)

#!/usr/bin/env bash
last_line=''
while IFS= read -r line; do
  [[ $line = '!' && $last_line = '!' ]] && continue
  printf '%s\n' "$line"
  last_line=$line
done

看到它运行在https://ideone.com/eu7UHm上,输出为:

!interface vlan200
!description 
!
interface vlan201

答案 2 :(得分:1)

抢救Perl:

perl -ne 'print unless /^!$/ and $previous; $previous = /^!$/' -- file
  • -n逐行读取输入
  • 如果当前行包含单个$previous,则变量!设置为true,在处理下一行以决定是否打印时使用其值。

答案 3 :(得分:1)

带有sed,应OP要求:

sed -nr 'p;:loop;$!N;s/^(\!)\n\1$/\1/;tloop;D'

注意:这是sed常用单线之一的细微调整(仅与感叹号匹配),请参见:http://sed.sourceforge.net/sed1line.txt

答案 4 :(得分:1)

sed用于做旧/新/旧,仅此

$ awk '$0!=p || $0!="!"; {p=$0}' file
!interface vlan200
!description
!
interface vlan201

以上内容适用于任何UNIX盒子上任何shell中的任何awk。它只是说如果当前行与最后一行不同或者当前行不是!,然后打印它。然后将当前要测试的行保存到下一行。

答案 5 :(得分:0)

这可能对您有用(GNU sed):

sed 'N;/^!\n!$/!P;D' file

打开两行窗口,如果第一行和第二行以!开头和结尾,则删除(不打印)第一行。