請幫我弄清楚如何根據關鍵字提取多個子字串。我一直在努力嘗試使用分隔符號的不同方法
我的輸入:
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
前三個變數a
、b
和c
被設定為目前輸入 record( $0
)。然後內建函數gsub()
將正規表示式變更為空字串(""
)。這裡的正規表示式(/^.*Inventory for | .*$/
使用交替有兩種模式/^.*Inventory for /
和/ .*$/
。交替允許在正規表示式中使用
|
.將gsub()
from start of line( ^
)Inventory for
更改為""
。這意味著從行首到我們想要的第一個字串的所有字元都將被刪除。類似地,從空格(我們想要的第一個字串之後)到行尾都會更改為""
。同樣/^.*PID: |,.*$/
有兩個替代模式
/^.*PID: /
和 /,.*$/
。這兩個都改為""
.
接下來sub()
更改/^.*SN: /
為空字串並substr(c,1,11)
從 中取得 11 個字元長的字串c
。