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 

4 Answers 4

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"
2
  • 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" Feb 26, 2019 at 4:41
  • Example added. But I didn't use sed :)
    – Freddy
    Feb 26, 2019 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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .