执行后我有这个输出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 开始编号)。