我想将匹配的模式与awk在 Solaris 系统上。
$ luxadm probe
No Network Array enclosures found in /dev/es
Found Fibre Channel device(s):
Node WWN:2000000c50f1c8da Device Type:Disk device
Logical Path:/dev/rdsk/c1t1d0s2
Node WWN:2000000c50f1d9c9 Device Type:Disk device
Logical Path:/dev/rdsk/c1t0d0s2
注意 - 当我尝试使用awk,只需要从最后一行合并一行。
$ luxadm probe |awk '/Node/{n=$2}/Logical/{l=$2} END {print n,l}'
WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2
虽然预期的输出是:
WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2
WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2
答案1
尚未提及的简短答案awk
awk '/Node/{n=$2; getline; print n " "$2; next}' filename
/Node/
# 查找模式节点并将第二个字段存储在n
变量中n=$2
getline
# 移动到下一行(这是Logical
行开始的地方),打印变量中存储的内容n
,然后打印下一行的第二个字段。next
# 停止处理当前记录并移至下一条记录。
答案2
它失败的原因是因为您只在一个块中打印一次捕获的变量END{}
。这意味着仅打印最后两个。 @Costas 已经为您提供了一种更优雅的方法,但您也可以使用您尝试的相同逻辑进行一些小更改:
awk '{ if(/Node/){
if(length(n)){print n,l} ## if we have an n, print them
n=$2
}
if(/Logical/){l=$2}
}
END {print n,l}'
或者,您可以使用其他工具:
GNU grep/perl
luxadm probe | grep -Po '^\s*(Node|Logical)\s*\K.*?(\s|$)' file | perl -lne '$. % 2 ? printf : print'
珀尔
luxadm probe | perl -ne 'chomp;if(s/.*(WWN:.*?)\s.*/$1 / || s/.*(Path:.*?)$/$1\n/){print}'
答案3
sed
我认为你应该使用。首先,它通常会优于awk
,并且在这种情况下,它总体上提供了更简单的解决方案:
sed -n 'N;s/Node \([^ ]*\).*Logical/\1/p' <infile
...根据您的示例数据,打印...
WWN:2000000c50f1c8da Path:/dev/rdsk/c1t1d0s2
WWN:2000000c50f1d9c9 Path:/dev/rdsk/c1t0d0s2
对于读取的每一行,sed
还会将N
ext 附加到模式空间中插入的\n
行分隔符之后。因此,上面的s///
替换跨越两行,并且仅在找到匹配项时才打印您想要仅用空格分隔的两个字段。
上述sed
语法应该完全可移植到任何 POSIX 系统。
答案4
如果你想awk
awk -v RS=' Node ' -v FS=' Logical Path:| ' '/WWN/{print $1,$6}'
其他(可能很简单)
awk -F":| " '/Node/{printf "%s ", $3":"$4}/Logical Path/{print $4}'
与剩余Path:
awk '/Node/{printf "%s ", $2}/Logical Path/{print $2}'
或者
awk '/Node/{wwn=$2}/Logical Path/{print wwn,$2}'
sed
最后是GNU :
sed -n '/WWN/{s/^\s*\S* *\|\( \S*\)\{3\}\s*$//g;N;s/\n\s*\S*//;p}'