텍스트 파일에서 특정 값/필드를 추출하는 방법은 무엇입니까?

텍스트 파일에서 특정 값/필드를 추출하는 방법은 무엇입니까?

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에서는 많은 언어와 마찬가지로 ||논리적 OR을 의미합니다. ^EventCorrelationId=/ || /^CreationTime=/정규식이 일치하면 참입니다.

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 -Eo확장된 정규식 모드에서 grep(이스케이프된 특수 문자가 적음) 및 일치하는 부분만 인쇄
  • (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을 연결하여 각각을 변환합니다 |.
  • 마지막 단계에서는 현재 레코드에 방금 구축한 정규식을 적용 $_하고 낚시된 필드를 파이프하여 |출력을 얻습니다.

관련 정보