Bash скрипт для итерации записей в файле и извлечения значения на основе условия

Буду признателен за любую помощь по нижеприведенному запросу. Потребуется сценарий bash. Я новичок в этой технологии написания сценариев.

У меня есть нижеприведенный файл в некотором месте - скажем, имя файла MemberFile.txt.

#
[ID          ]  #1
[ADDRE1      ]  Address Line #1
[ADDRE2      ]  Mumbai City
[ADDRE3      ]  India
#
[ID          ]  #2
[ADDRE1      ]  House No 2
[ADDRE3      ]  Green Society
[ADDRE4      ]  Kolkatta
#
[ID          ]  #3
[ADDRE1      ]  Plot Num 77
[ADDRE2      ]  House No # [567]
[ADDRE3      ]  greener Apt
#

Файл может содержать миллионы таких записей. Я хотел бы быстро просмотреть каждую запись, получить и сохранить значение для [ADDRE3 ]. Также проверьте, содержит ли эта запись слово 'society' или 'Num' (без учета регистра). Если да, то получите значение тега [ID ] в этой записи.

Ожидаемый результат - #2 и #3.

Обратите внимание, что ниже единица обозначает одну запись.

[ID          ]  #1
[ADDRE1      ]  Address Line #1
[ADDRE2      ]  Mumbai City
[ADDRE3      ]  India
-2
12.07.2017, 14:09
3 ответа

awkрешение:

awk -v IGNORECASE=1 '/\[ID /{ r=$3; c=3; next }c-- && $0~/society/{ print r }' MemberFile.txt

Выход:

#2
#3

  • IGNORECASE=1-установить режим сравнения без учета регистра

  • /\[ID /{ r=$3; c=3; next }-захват IDномера записи#<number>(в качестве 3-го поля)

  • c-- && $0~/society/-проверить, содержит ли какая-либо из 3 следующих записей societyслово

0
28.01.2020, 05:17

Это поможет:

grep -iE '(^\[ADDRE3.*society|^\[ADDRE3.*no|^\[ADDRE3.*blabla)' -B 3 MemberFile.txt | grep "ID" | grep -o "#[0-9]*"

Написано, что именно происходит:

Таким образом, мы фильтруем регистр без учета регистра -iс регулярным выражением -Eпосле каждой строки, которая начинается с «[ADDRE3» ^\[ADDRE3с любым количеством текста между ними .*, пока мы не найдем нужное имя societyили |другие вещи.

Если мы получаем попадание, мы отображаем строку + 3 строки -B 3над ней.

Затем мы фильтруем все строки по идентификатору, который затем фильтруем после #номера, который мы только отображаем-o

Поиск любого адреса:

grep -iE '(^\[ADDRE.*society|^\[ADDRE.*no|^\[ADDRE.*blabla)' -B 3 MemberFile.txt | grep "ID" | grep -o "#[0-9]*"
0
28.01.2020, 05:17
perl -lne '
   next unless /^#$/ && !$flag... /^#$/ && $flag;
   $flag++,next if /^#$/ && !$flag;
   /^\[ID\h/ and $id = s/.*\h#/#/r,next;
   push @A, $_;
   if ( (/^#$/ && $flag) ) {
      print $id if join($/, splice(@A,0,@A)) =~ /(?:^|\h)(?i:society|num)(?:\h|$)/m;
      $flag = 0; undef $id; redo;
   }
' MemberFile.txt

Работа

Каждая запись начинается с#(при выключенном флаге )и заканчивается при включенном флаге#(). Первое действие, которое следует предпринять при обнаружении новой записи, — это включить флаг. (так же, как если бы вы включали свет, входя в комнату ).

При встрече строки идентификатора в записи сохраните ее значение. Для всех остальных строк в записи сохраните каждую в массив @A.

При попадании в последнюю строку записи (/ #/ с включенным флагом )вывести идентификатор при условии, что элементы массива, связанные с новыми строками, как известно, содержат слова «общество» или «число». Обратите внимание, что spliceочищает массив.

Мы выключаем флаг (, как и следует при выходе из комнаты )и redo, а не next, так как эту же строку мы будем каннибализировать для начала следующей записи.

Мы в значительной степени используем тот же метод с sed, но, поскольку он не имеет массивов, мы используем пространство хранения для наших целей хранения. Обратите внимание, что этот код совместим с POSIX, с GNUsed-isms его можно было бы немного сократить.

sed -e '
   /^\[ID[[:blank:]]/,/^#$/!d
   H;/^\[ID[[:blank:]]/h;/^#$/!d
   g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
   /[[:blank:]]num$/ba
   /[[:blank:]]society$/ba
   /[[:blank:]]num\n/ba
   /[[:blank:]]society\n/ba
   /[[:blank:]]num[[:blank:]]/ba
   /[[:blank:]]society[[:blank:]]/ba
   d;:a
   s/\n.*//
   s/^\[id[[:blank:]].*#/#/
' MemberFile.txt

Результаты

#2
#3
0
28.01.2020, 05:17

Теги

Похожие вопросы