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

Первая строка — это что-то между «Инвентарь для» и следующим пробелом.

Вторая строка — это что-то между «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.

Связанный контент