Пожалуйста, помогите мне разобраться, как извлечь несколько подстрок на основе ключевых слов. Я боролся с разными методами, используя разделители
Мой вклад:
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
Первая строка — это что-то между «Инвентарь для» и следующим пробелом.
Вторая строка — это что-то между «PID:» и запятой.
Третья строка — это строка из 11 символов после «SN:».
решение1
Использование любого sed в любой оболочке на любой машине Unix:
$ 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
устанавливаются в текущую входную запись ( $0
). Затем встроенная функция gsub()
изменяет регулярное выражение на пустую строку ( ""
). Регулярное выражение здесь (/^.*Inventory for | .*$/
использует чередование, имеет два шаблона /^.*Inventory for /
и / .*$/
. Чередование допускает альтернативный шаблон в регулярном выражении с
|
. С gsub()
from start of line( ^
) to Inventory for
изменяется на ""
. Это означает, что все символы от начала строки до первой нужной нам строки удаляются. Аналогично от пробела (после первой нужной нам строки) до конца строки изменяются на ""
. Аналогично /^.*PID: |,.*$/
имеет два альтернативных шаблона
/^.*PID: /
и /,.*$/
. Оба они изменяются на ""
.
Далее sub()
изменяется /^.*SN: /
на пустую строку и substr(c,1,11)
берется строка длиной 11 символов из c
.