-2

Appreciate if any help for below query. Will require bash script. I am new to this scripting technology.

I have the below file at some location - say filename as 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
#

File can have millions of such records. I wanted to quickly iterate through each record and get and store value for [ADDRE3 ]. Also check if that record contains either of word 'society' or 'Num' (case insensitive). If yes, then get value of tag [ID ] in that record.

Expected output is #2 and #3.

Please note that below one represents one record.

[ID          ]  #1
[ADDRE1      ]  Address Line #1
[ADDRE2      ]  Mumbai City
[ADDRE3      ]  India
0

awk solution:

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

The output:

#2
#3

  • IGNORECASE=1 - set caseinsensitive comparison mode

  • /\[ID /{ r=$3; c=3; next } - capturing ID record number #<number> (as the 3rd field)

  • c-- && $0~/society/ - check if any of the 3 following records contains society word

0

This would do the trick:

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

Written what is exactly happening:

So we are filtering caseinsensitive -i with regular expression -E on after every line that starts with "[ADDRE3" ^\[ADDRE3 with any amount of text inbetween .* until we hit our desired name society or | the other things.

If we get a hit we display the line + 3 lines -B 3 above it.

Then we filter all lines for ID which we afterwards filter after the #Number which we only display -o

Search any ADDRE:

grep -iE '(^\[ADDRE.*society|^\[ADDRE.*no|^\[ADDRE.*blabla)' -B 3 MemberFile.txt | grep "ID" | grep -o "#[0-9]*"
  • I wanted to iterate records as well. Lets say I want to get ADDR3 value from each record. Society is one word. What if we want to check multiple words. Check if it contains either of 'society' or 'No'. – NoviceUser Jul 12 '17 at 10:46
  • Adjusted it to be case insensitive and for more than one word. – Ziazis Jul 12 '17 at 10:53
  • Since you only want hits with [ADDRE3 we might need to adjust that a little more... – Ziazis Jul 12 '17 at 11:04
  • hits can be anywhere in the record and not with only tag [ADDR3. I want this tag irrespective of record contains hit or no. – NoviceUser Jul 12 '17 at 11:18
  • Lets first check as how we can get each record. I mean get all the three records. My intention is iterate through each record. Get the value for tag '[ADDR3 ]'. Check if that whole record contain any of the field 'society' or 'num'. if yes then get value for tag [ID ] of that record. – NoviceUser Jul 12 '17 at 11:20
0
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

Working

Each record starts with # (with flag OFF) and ends with # (flag ON). The first action to take upon encountering a fresh record is to turn ON the flag.(much like you would turn on the lights when entering a room).

When meeting the ID line in a record, save it's value. For all other lines in the record, save each into the array @A.

Upon hitting the last line of the record (/#/ with flag ON), print the id provided the array elements when strapped with newlines are known to contain words "society" or "num". Note that the splice empties the array.

We turn OFF the flag(as one should upon exiting a room) and redo rather than next since it's this same line we shall be cannibalizing for the beginning of the next record.

We pretty much use the same method using sed , but since it doesn't have arrays we make use of hold space for our storage purposes. Note that this code is POSIX compliant, with GNU sed-isms it could be condensed quite a bit.

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

Results

#2
#3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.