如何从文本文件中提取特定值/字段?

如何从文本文件中提取特定值/字段?

如何在 Linux 系统中从文本文件中提取以下值/字段:

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

文本文件样本数据如下:

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 

答案1

使用 grep

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

使用 awk

尝试:

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

怎么运行的

  • -v RS=' '

    这告诉 awk 使用空格作为记录分隔符。

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

    这告诉 awk 如果记录与这三个正则表达式中的任何一个匹配,则打印该记录。一些注意事项:

    • 在正则表达式中,^表示记录的开头。因此/^CreationTime=/意味着以以下开头的记录CreationTime=

    • 在 awk 中,像许多语言一样,||意味着逻辑或。^EventCorrelationId=/ || /^CreationTime=/如果任一正则表达式匹配,则为true。

使用 sed

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

在输出中使用备用分隔符

用作|输出分隔符代替换行符:

$ 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 -Eogrep 在扩展正则表达式模式下(较少转义特殊字符)并仅打印匹配的部分
  • (EventCorrelationId|CreationTime|SubscriberNumber)匹配 EventCorrelationId 或 CreationTime 或 SubscriberNumber
  • =[^ ]+后跟“=”,后跟一次或多次非空格字符

编辑1:

现在用“|”分隔:

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

编辑2:

现在用“|”分隔以相反的顺序使用tac

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

答案3

我尝试使用下面的 awk 方法,效果很好

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

输出

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

答案4

您可以根据要输出的字段动态构建正则表达式来执行此练习:

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

输出:

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

在职的:

  • 您想要输出的字段放置在匿名数组中qw/.../
  • map { ... }然后我们通过连接逻辑 OR来转换它们中的每一个|
  • 在最后一步中,我们应用刚刚在当前记录上构建的正则表达式 ,$_并通过管道符号连接捞出的字段|以获取输出。

相关内容