使用 sed 对输出进行排序

使用 sed 对输出进行排序

执行后我有这个输出diff

< #R1#Number = Gauge32: 258     Name = STRING: "TATA"
---
> #R1#Number = Gauge32: 280     Name = STRING: "TATA"

我需要在 shell 脚本中实现 sed 命令以获得以下输出:

Hostname=R1; old=258 new=280, Name="TATA"

答案1

尝试这个:

diff ... | sed -n -e '
    /^< / h
    /^---/ H
    /^> / { H; x; s/\n//g;
            s/^< #\([^#][^#]*\)#Number = Gauge32: \([0-9][0-9]*\) .* #\1#Number = Gauge32: \([0-9][0-9]*\) .* Name = STRING: \("[^"]*"\).*/Hostname=\1; old=\2 new=\3, Name=\4/;
            p; }'

这个想法是将所有内容都放在一行中,然后只选择有趣的内容。

详细地:

  • sed -n- 默认情况下不打印任何内容
  • /^< / h- 将开头的行复制到<保留空间
  • /^---/ H- 将以 开头的行附加---到保留空间
  • /^> / { ... }- 对于以>以下方式开头的行:
  • H- 将行附加到保留空间
  • x- 交换保持空间和图案空间
  • s/\n//g- 删除换行符;此时模式空间包含如下内容:< #R1#Number = Gauge32: 258 Name = STRING: "TATA"---> #R1#Number = Gauge32: 280 Name = STRING: "TATA"
  • s/.../.../- 格式化输出(这里没什么聪明的,只是简单的sed-fu)
  • p- 打印

这不适用于一般diff输出,因为相邻行可能会发生更改。但它确实按照您提出的方式回答了问题。

答案2

你也可以尝试 Perl:

diff file1 file2 | 
    perl -lne 'if(/^(.).*?#(.+?)#.*?:\s*(\d+).*(".+?")/){
        $1 eq ">" ? print "Hostname=$2; old=$o new=$3, Name=$4" : ( $o=$3 )}'

解释

  • 为每个调用添加一个换行符,并且将-l导致给定的脚本应用于输入文件的每一行。print-n-e
  • 正则表达式将识别第一个字符 ( )、 ( )^.之间的第一个字符串、后跟 0 个或多个空格和一组数字 ( ) 以及行上最后一个引用的字符串 ( )。括号使这些被保存为through 。##(.+?)#::\s*(\d+).*(".+?")$1$4
  • foo ? bar : baz:这是许多语言中都存在的 C 结构。它是“如果 foo 为 true,则执行 bar,否则执行 baz”的简写。因此,如果$1上一个匹配操作保存的行的第一个字符是>,那么我们将打印,如果不是,我们将把匹配的第三个模式保存为$o

或者

diff file1 file2 | 
    perl -lane '$o = $F[4] if /^</; $F[1]=~s/#(.*)#.*/$1/; 
        print "Hostname=$F[1]; old=$o new=$F[4], Name=$F[8]" if />/'

解释

  • -a将导致 Perl 自动在空白处分割每个输入行并将其保存在@F数组中。
  • $o = $F[4] if /^</;:这会保存第 5 个字段,就像$o该行的第一个字符是 一样<
  • $F[1]=~s/#(.*)#.*/$1/;:这将从第二个字段中删除除主机名之外的所有内容($F[1]数组从 0 开始编号)。

相关内容