4

How to extract the following values/fields from the text file in Linux system:

EventCorrelationId="615-493|-1899671563||1550927718000"
CreationTime="20190225094504"
SubscriberNumber=92705073362

Text file sample data is mentioned below:

2019-02-25 09:45:04.427 FAIL RETRY: Failed for request id: 11235993 Cause: userNotReachable Info: <undef> Code: 27,USSD RequestId=11235993 OriginalId=11235993 EventCorrelationId="615-493|-1899671563||1550927718000" CreationTime="20190225094504" ResendCount=0 Timestamp=1551071704342 (Mon Feb 25 09:45:04 AFT 2019) State=STATE_SENT SubscriberNumber=92705073362 UssdText=Last event was charged 687.95 MB from 3GB Monthly, Main Account 6.00 PKR, Remaining data 2,388.75 MB (Exp 25.03.2019), Main Account 7.62 PKR1500 PKR = 32GB valid 30 Days, Dial *477*32*1#. NumberingPlan=1 Nadi=4 UssdFormat=2 
3

Using grep

$ grep -oE '(EventCorrelationId|CreationTime|SubscriberNumber)[^ ]*' textfile
EventCorrelationId="615-493|-1899671563||1550927718000"
CreationTime="20190225094504"
SubscriberNumber=92705073362

Using awk

Try:

$ awk -v RS=' ' '/^EventCorrelationId=/ || /^CreationTime=/ || /^SubscriberNumber=/' textfile
EventCorrelationId="615-493|-1899671563||1550927718000"
CreationTime="20190225094504"
SubscriberNumber=92705073362

How it works

  • -v RS=' '

    This tells awk to use a blank as the record separator.

  • /^EventCorrelationId=/ || /^CreationTime=/ || /^SubscriberNumber=/

    This tells awk to print the record if it matches any of these three regular expressions. Some notes:

    • In a regex, ^ means beginning-of-the-record. Thus /^CreationTime=/ means a record that starts with CreationTime=

    • In awk, like many languages, || means logical-or. Thus ^EventCorrelationId=/ || /^CreationTime=/ is true if either regex is matched.

Using sed

$ sed -En 's/.*(EventCorrelationId=[^ ]*).*(CreationTime=[^ ]*).*(SubscriberNumber=[^ ]*).*/\1\n\2\n\3/p' textfile
EventCorrelationId="615-493|-1899671563||1550927718000"
CreationTime="20190225094504"
SubscriberNumber=92705073362

Using an alternate separator in the output

To use | as the output separator in place of newline:

$ sed -En 's/.*(EventCorrelationId=[^ ]*).*(CreationTime=[^ ]*).*(SubscriberNumber=[^ ]*).*/\1|\2|\3/p' textfile
EventCorrelationId="615-493|-1899671563||1550927718000"|CreationTime="20190225094504"|SubscriberNumber=92705073362
2
$ grep -Eo '(EventCorrelationId|CreationTime|SubscriberNumber)=[^ ]+' file
EventCorrelationId="615-493|-1899671563||1550927718000"
CreationTime="20190225094504"
SubscriberNumber=92705073362
  • grep -Eo grep in extended regular expression mode (less escaping of special chars) and print only the matched parts
  • (EventCorrelationId|CreationTime|SubscriberNumber) match EventCorrelationId or CreationTime or SubscriberNumber
  • =[^ ]+ followed by "=", followed by non-space-character one or more times

Edit1:

Now separated by "|":

$ echo $(grep -Eo '(EventCorrelationId|CreationTime|SubscriberNumber)=[^ ]+' file) | tr ' ' '|'
EventCorrelationId="615-493|-1899671563||1550927718000"|CreationTime="20190225094504"|SubscriberNumber=92705073362

Edit2:

Now separated by "|" in reversed order using tac:

$ echo $(grep -Eo '(EventCorrelationId|CreationTime|SubscriberNumber)=[^ ]+' file | tac) | tr ' ' '|'
SubscriberNumber=92705073362|CreationTime="20190225094504"|EventCorrelationId="615-493|-1899671563||1550927718000"
  • hanks for your kind support, using your (Using sed) command, I was able to extract the information. However, kindly to please suggest how to extract the mentioned values in one single line separated by "|" sign as shown below? SubscriberNumber=92705073362|CreationTime="20190225094504"|EventCorrelationId="615-493|-1899671563||1550927718000" – Jack Anderson Feb 26 at 4:41
  • Example added. But I didn't use sed :) – Freddy Feb 26 at 4:56
0

I Tried with below awk method and it worked fine

j=`awk '{print NF}' filename `
for ((i=1;i<=$j;i++)); do awk -v i="$i" '$i ~ /EventCorrelationId/||$i ~ /CreationTime/||$i ~ /SubscriberNumber/{print $i}' filename ; done

output

EventCorrelationId="615-493|-1899671563||1550927718000"
CreationTime="20190225094504"
SubscriberNumber=9270507336
0

You can perform this exercise bu building up your regex dynamically, based on the fields you want outputted:

$ perl -lne '
   $re = join "|", map { +quotemeta } qw/EventCorrelationId CreationTime SubscriberNumber/;
   print join "|",  /(?:$re)=\H+/g;
' input.file

Output:

EventCorrelationId="615-493|-1899671563||1550927718000"|CreationTime="20190225094504"|SubscriberNumber=92705073362

Working:

  • The fields that you want output are placed in an anonymous array qw/.../.
  • Then we transform each of them using map { ... } by joining with logical OR |.
  • In the last step, we apply the regex just constructed on the current record, $_, and the fields fished out are joined via the pipe symbol | to get the output.

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.