Буду признателен за любую помощь по нижеприведенному запросу. Потребуется сценарий 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
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
слово
Это поможет:
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]*"
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