awk는 세 번째와 네 번째 패턴을 일치시키고 한 줄에 인쇄합니다.

awk는 세 번째와 네 번째 패턴을 일치시키고 한 줄에 인쇄합니다.

처음에 나는 이것에 대한 해결책을 얻었습니다.우편 엽서.

그러나 이는 2가지 모드에서만 사용할 수 있습니다. 이제 2개 이상의 패턴, 어쩌면 3번째 패턴, 심지어 4번째 패턴이 필요하다는 것이 밝혀졌습니다.

@cas에서 얻은 패턴을 더 추가하여 다음 솔루션을 사용해 보았습니다.

awk -v OFS=, '
match($0,/\<[[:digit:]]{1,2}\/[[:digit:]]{1,2}\/[[:digit:]]{4} [[:digit:]]{1,2}:[[:digit:]]{1,2}\>/,a) {dt = a[0]; next};
match($0,/3rd pattern/,b);
match($0,/INC-[[:digit:]]+-[[:digit:]]+/,a) {print a[0], dt; print b[0]}' filename.log

나는 다음과 같은 결과를 얻었습니다.

INC-210305-00000426,3/6/2021 5:19

INC-20210304-00006690,3/5/2021 5:24

공간을 더 추가하면 됩니다. 세 번째 또는 네 번째 패턴을 찾는 방법에 대한 다른 제안이 있습니까? 그들은 실제로 다른 노선에 있습니다. 입력은 다음과 같습니다.

unwantedtext unwantedtext unwantedtext unwantedtext 8/1/2022 6:15 (1st Pattern)

unwantedtext unwantedtext unwantedtext unwantedtext 
unwantedtext unwantedtext Report_A (3rd Pattern)
unwantedtext unwantedtext INC-220721-00007628 (2nd required pattern)
unwantedtext unwantedtext unwantedtext unwantedtext 
unwantedtext unwantedtext Report_B (4th) Pattern)

원하는 출력은 다음과 같습니다.

INC-220721-00007628, 8/1/2022 6:15, Report_A

나중에 다음 출력이 필요할 수도 있습니다.

INC-220721-00007628, 8/1/2022 6:15, Report_A, Report_B

저는 Cygwin과 CentOS 7 환경을 사용하고 있습니다.

유용한 솔루션에 미리 감사드립니다.

답변1

perl대신 사용하겠습니다 awk(gawk도 사용합니다. 사용하는 코드는 gawk에 따라 다릅니다).

perl -l -0777 -ne '
  $time = $& if m{\b\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{1,2}\b};
  $inc = $& if /\bINC-\d+-\d+\b/;
  @reports = /\bReport_\S+/g;
  print join ", ", $inc, $time, @reports
    if defined($time) && defined($inc)' your-file

답변2

존재하다TxR:

$ txr extract.txr input
INC-220721-00007628, 8/1/2022 6:15, Report_A, Report_B

어디 extract.txr:

@(skip)@{date /[^ ]+/} @{time /[^ ]+/} (1st Pattern)
@(skip)
@(skip)@{rep1 /[^ ]+/} (3rd Pattern)
@(skip)INC-@inccode (2nd required pattern)
@(skip)
@(skip)@{rep2 /[^ ]+/} (4th) Pattern)
@(output)
INC-@inccode, @date @time, @rep1, @rep2
@(end)

줄 끝의 패턴을 일치시키려면 여기에 약간의 정규 표현식이 필요합니다. 텍스트 캡처와 유사한 변수에는 @date공백이 포함될 수 있지만 @{date /[^ ]+/}공백이 아닌 일련의 문자를 캡처할 수 있습니다.

출력은 단 한 줄이므로 @(output)...에 포함된 Lisp 함수 호출로 바꿀 수 있습니다.@(end)@(do ...)

@(do (put-line `INC-@inccode, @date @time, @rep1, @rep2`))

답변3

POSIX awk를 사용하십시오.

$ cat tst.awk
match($0,/([0-9]{1,2}\/){2}[0-9]{4} [0-9]{1,2}:[0-9]{1,2}/) { dt = substr($0,RSTART,RLENGTH) }
match($0,/INC(-[0-9]+){2}/) { inc  = substr($0,RSTART,RLENGTH) }
match($0,/Report_A/)        { repa = substr($0,RSTART,RLENGTH) }
match($0,/Report_B/)        { repb = substr($0,RSTART,RLENGTH) }
END { OFS=", "; print inc, dt, repa, repb }

$ awk -f tst.awk file
INC-220721-00007628, 8/1/2022 6:15, Report_A, Report_B

위의 내용은 대상 정규식의 중간 단어와 일치합니다. 질문의 예에서 이것이 가능성이라고 표시하지 않았지만 이것이 실제 데이터에 문제가 있는 경우 다음과 같이 변경하십시오.

$ cat tst.awk
function set(val) {
    val = substr($0,RSTART,RLENGTH)
    gsub(/^ | $/,"",val)
    return val
}
match($0,/(^| )([0-9]{1,2}\/){2}[0-9]{4} [0-9]{1,2}:[0-9]{1,2}( |$)/) { dt = set() }
match($0,/(^| )INC(-[0-9]+){2}( |$)/) { inc  = set() }
match($0,/(^| )Report_A( |$)/)        { repa = set() }
match($0,/(^| )Report_B( |$)/)        { repb = set() }
END { OFS=", "; print inc, dt, repa, repb }

관련 정보