Изучите несколько мест в строке для данных, используя awk - PullRequest
0 голосов
/ 01 февраля 2019

Я пытаюсь извлечь некоторую информацию, которая первоначально была получена из мэйнфрейма.Все строки являются просто символьными данными ASCII, но каждая строка считается многосегментной, поэтому имеет различную длину строки.Поля ограничены по длине.В строке есть поле, которое определяет, сколько сегментов строки ожидать для переменной части.Что я хочу сделать, так это посмотреть на наличие индикатора в этих переменных сегментах и ​​извлечь из него некоторые данные.

Упрощенный пример показан ниже;

UUID12345 1   ABC 1 345  
UUID23456 2   XYZ 4 763 ABC 4 678  
UUID34567 3   XYZ 4 763 ABC 2 456 QRS 2 456  
UUID45678 2   DEF 1 345 TUV 8 111 
UUID56789 0

Во втором столбце указывается, сколько сегментов ожидать.Там может быть до 99 сегментов, но на самом деле их меньше 10. В приведенном выше примере каждый сегмент будет содержать 10 байтов, начиная, например, с позиции ABC в первой строке.То, что я хочу извлечь, это первый столбец каждой строки и значение, которое является последними 3 символами любого сегмента, содержащего ABC.

Таким образом, пример выходных данных для вышеприведенной строки мог бы быть:

UUID12345 345  
UUID23456 678  
UUID34567 456
UUID45678 
UUID56789 

Я знаю очень простой awk и могу искать определенные участки строки, но не знаю какчтобы добиться того, что мне нужно для этого.Например, следующее дает мне возможность извлечь первую строку, но только путем просмотра определенных местоположений, и не учитывает 2-й столбец, указывающий переменное количество сегментов.

awk '{ if (substr($0, 0, 4)=="UUID" && substr($0, 15, 3)=="ABC") {print substr($0, 0, 9) " " substr ($0, 21,3)}}' <<< "UUID12345 1   ABC 1 345"

Редактировать

В соответствии с моим комментарием к Эду Мортону ниже, это то, что я закончил, это работает для меня (где test.txt - пример, показанный выше);

awk '{segs=substr($0, 11, 1); acc=substr($0, 1, 10); startCol=15; val=""; for(i=startCol; i<startCol+(10 * segs); i+= 10) if (substr($0, i, 3)=="ABC") val=substr($0, i + 6, 3); print acc " " segs " " val}' test.txt

Ответы [ 3 ]

0 голосов
/ 01 февраля 2019

Другой способ с awk:

awk -F'ABC' '{split($1,a," |\t");split($2,b," |\t");print a[1],b[3]}' infile
0 голосов
/ 02 февраля 2019

Использование Perl

$ perl -lane ' ($x)=$_=~/\bABC\s+\S+\s+(\S+)/; print $F[0], " ", $x ' moose.txt
UUID12345 345
UUID23456 678
UUID34567 456
UUID45678
UUID56789

$ cat moose.txt
UUID12345 1   ABC 1 345
UUID23456 2   XYZ 4 763 ABC 4 678
UUID34567 3   XYZ 4 763 ABC 2 456 QRS 2 456
UUID45678 2   DEF 1 345 TUV 8 111
UUID56789 0

$
0 голосов
/ 01 февраля 2019
$ awk '{val=""; for (i=3; i<NF; i+=3) if ($i=="ABC") val=$(i+2); print $1, val}' file
UUID12345 345
UUID23456 678
UUID34567 456
UUID45678
UUID56789

Если это не все, что вам нужно, отредактируйте ваш вопрос, чтобы обеспечить более по-настоящему репрезентативный пример ввода / вывода, который лучше отражает все ваши требования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...