패턴과 일치하는 로그 파일에서 숫자를 찾는 방법

패턴과 일치하는 로그 파일에서 숫자를 찾는 방법

다음을 포함하는 로그 파일에서 일부 정보를 추출하고 싶습니다.

...
Running ep. 0
...
...
Initial position for this ep is 7.338690864048985,28.51815509409351,11.795143979909135
...
...
...
Running ep. 1
...
...
Initial position for this ep is 10.599326804010953,7.514871863851674,14.843070346933654
...
...

이제 일부 데이터를 추출할 수 있는 bash 코드가 생겼습니다.

cat screen2.dat|grep -oP 'Running ep. \K([0-9]+)|(?<=for this ep is )[+-]?[0-9]+([.][0-9]+)?'|paste -d' ' - -

그러나 출력은 "Running ep" 이후의 숫자일 뿐입니다. "이 ep의 초기 위치는" 다음의 첫 번째 숫자입니다.

0 7.338690864048985 
1 10.599326804010953 
.
.
.

나는 다음과 같은 것을 기대하고 있었다

0 7.338690864048985 28.51815509409351 11.795143979909135
1 10.599326804010953 7.514871863851674 14.843070346933654
.
.
.

답변1

표현을 너무 과하게 지정하신 것 같네요. substring 뒤에 단일 float만 일치합니다 for this ep is. 나머지 줄을 원하면 다음과 같은 것을 사용하십시오

grep -oP 'Running ep\. \K(.*)|for this ep is \K(.*)' screen2.dat |
paste -d ' ' - -

표준을 사용하여 sed다음을 작성할 수 있습니다.

sed -n -e 's/^Running ep\. //p' -e 's/.*for this ep is //p' screen2.dat |
paste -d ' ' - -

선의 불필요한 부분을 잘라냅니다(제거할 항목이 없는 것으로 교체).

awk같은 방법으로 사용 하셔도 되고 ,

awk '/^Running ep\. / || /for this ep is / { print $NF }' screen2.dat |
paste -d ' ' - -

아니면 한번에 모든 것을 포맷하고,

awk '/^Running ep\. / { ep = $NF } /for this ep is / { print ep, $NF }' screen2.dat

답변2

귀하의 코드는 [+-]?[0-9]+([.][0-9]+)?점 뒤에 선택적 숫자가 있는 단일 숫자와 일치합니다. 3개를 원하시면 이렇게 말씀하세요.([+-]?[0-9]+([.][0-9]+)?,?){3}

하지만 당신이 정말로 원하는 것은 sed단지 스크립트에 불과합니다:

sed -e '/Running ep. /{s///;h;}' -e '/.*for this ep is /!d;s///;H;x;s/[\n,]/ /g' screen2.dat
  • /Running ep. /{...}{}일치하는 줄 안에서만 모든 것을 실행하는 것입니다.Running ep.
  • 이러한 행의 경우 s///이전에 일치한 부분을 삭제하고 행을 h이전 공간 으로 이동합니다.
  • /.*for this ep is /!dNo !다른 패턴과 일치하지 않는 ( )가 있는 모든 행을 d선택할 수 있으며,
  • 나머지는 s///패턴을 다시 제거하고 행의 나머지 부분은 모두 숫자로 남겨 두십시오.
  • Hep 번호를 얻을 수 있는 예약된 공간에 이 나머지를 추가합니다.
  • x버퍼를 교환하여 예약된 공간에서 수집한 두 부분이 이제 패턴 공간에 있게 됩니다.
  • s/[\n,]/ /g포함된 줄바꿈과 모든 쉼표를 공백으로 바꾸기

답변3

와 궁극 pcregrepM모드:

$ <input pcregrep -M -o{1..4} --om-separator=' ' \
  '(?sm)^Running ep\. (\d+)$.*?^Initial position for this ep is ([+-]?\d+(?:\.\d+)?),((?2)),((?2))$'
0 7.338690864048985 28.51815509409351 11.795143979909135
1 10.599326804010953 7.514871863851674 14.843070346933654

그러나 Initial...특정 항목이 누락된 경우 다른 항목과 일치하게 되며Running ep... 주어진 값 집합 앞에 잘못된 ep 번호가 표시될 수 있습니다..*?Running ep...

아마도 gawk다음과 같이 하는 것이 더 나을 것입니다:

<input gawk -v 'FPAT=[+-]?[0-9]+([.][0-9]+)?' '
  /^Running ep/ && NF == 1 {ep = $1; next}
  /^Initial position for this ep is/ && ep != "" && NF == 3 {
    print ep, $1, $2, $3
    ep = "" # omit if there can be more than one "Initial position"
            # per ep.
  }'

여기서 FPAT필드는 정규식(숫자)과 일치하는 문자열로 정의되며 출력 한 줄만 인쇄합니다.초기 위치좋아, 해당하는 것이 있다면러닝 EP그 줄은 이전에 본 적이 있습니다.

답변4

모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.

$ awk '/Running ep/{ep=$NF} /Initial position/{print ep, $NF}' file
0 7.338690864048985,28.51815509409351,11.795143979909135
1 10.599326804010953,7.514871863851674,14.843070346933654

해당 쉼표를 공백으로 바꾸려면 다음을 수행하십시오.

$ awk '/Running ep/{ep=$NF} /Initial position/{gsub(/,/," ",$NF); print ep, $NF}' file
0 7.338690864048985 28.51815509409351 11.795143979909135
1 10.599326804010953 7.514871863851674 14.843070346933654

관련 정보