Bash awk/sed 使用关键字从单个大字符串中提取多个字符串

Bash awk/sed 使用关键字从单个大字符串中提取多个字符串

请帮我弄清楚如何根据关键字提取多个子字符串。我一直在努力尝试使用分隔符的不同方法

我的输入:

Inventory for 30844-ap01 NAME: AP1800 , DESCR: Cisco Aironet 1800 Series (IEEE 802.11ac) Access Point PID: AIR-AP1832I-E-K9, VID: V03, SN: KWC21420CKU
Inventory for ckh.hq-ap99 NAME: AP2700 , DESCR: Cisco Aironet 2700 Series (IEEE 802.11n) Access Point PID: AIR-CAP2702I-E-K9, VID: V03, SN: FCW2007N0ZQ
Inventory for AP0042.6843.ab78 NAME:  , DESCR:  PID: AIR-CAP1702I-E-K9, VID: V, SN: FCZ201622NY

期望的输出:

30844-ap01 AIR-AP1832I-E-K9 KWC21420CKU
ckh.hq-ap99 AIR-CAP2702I-E-K9 FCW2007N0ZQ
AP0042.6843.ab78 AIR-CAP1702I-E-K9 FCZ201622NY

第一个字符串是“Inventory for”和下一个空格之间的任何内容

第二个字符串是“PID:”和逗号之间的任何内容

第三个字符串是“SN:”之后的 11 个字符的字符串

答案1

在每个 Unix 机器上的任何 shell 中使用任何 sed:

$ sed 's/Inventory for \([^ ]*\).*PID: \([^,]*\).*SN:/\1 \2/' file
30844-ap01 AIR-AP1832I-E-K9 KWC21420CKU
ckh.hq-ap99 AIR-CAP2702I-E-K9 FCW2007N0ZQ
AP0042.6843.ab78 AIR-CAP1702I-E-K9 FCZ201622NY

答案2

我认为完成此类工作的最佳工具具有grep以下PCRE功能:

grep -Po '(?<=Inventory for )[^ ]+|(?<=PID: )[^,]+|(?<=SN: ).{11}' data

但这有一个缺点,就是在单独的行中打印每个匹配项:

30844-ap01
AIR-AP1832I-E-K9
KWC21420CKU
ckh.hq-ap99
AIR-CAP2702I-E-K9
FCW2007N0ZQ
AP0042.6843.ab78
AIR-CAP1702I-E-K9
FCZ201622NY

因此,让我们切换到perl并执行相同的操作:

perl -lne ' $i = $& if /(?<=Inventory for )[^ ]+/; $p = $& if /(?<=PID: )[^,]+/ ; $s = $& if /(?<=SN: ).{11}/; print join " ", $i, $p, $s' data

打印:

30844-ap01 AIR-AP1832I-E-K9 KWC21420CKU
ckh.hq-ap99 AIR-CAP2702I-E-K9 FCW2007N0ZQ
AP0042.6843.ab78 AIR-CAP1702I-E-K9 FCZ201622NY

答案3

使用gawk

awk '{a=b=c=$0;
gsub(/^.*Inventory for | .*$/,"",a);
gsub(/^.*PID: |,.*$/, "",b);
sub(/^.*SN: /,"",c); c=substr(c,1,11);
print a,b,c}' input

前三个变量abc被设置为当前输入 record( $0)。然后内置函数gsub()将正则表达式更改为空字符串("")。这里的正则表达式(/^.*Inventory for | .*$/使用交替有两种模式/^.*Inventory for // .*$/。交替允许在正则表达式中使用 |.将gsub()from start of line( ^)Inventory for更改为""。这意味着从行首到我们想要的第一个字符串的所有字符都将被删除。类似地,从空格(我们想要的第一个字符串之后)到行尾都更改为""。同样/^.*PID: |,.*$/有两个替代模式 /^.*PID: //,.*$/。这两个都改为"".

接下来sub()更改/^.*SN: /为空字符串并substr(c,1,11)从 中获取 11 个字符长的字符串c

相关内容