일반 텍스트 파일의 복잡한 패턴에서 숫자 데이터를 추출하고 표 형식의 출력을 생성합니다.

일반 텍스트 파일의 복잡한 패턴에서 숫자 데이터를 추출하고 표 형식의 출력을 생성합니다.

SOS 문제입니다. 교수님은 전직 박사후 연구원(나에게 그것이 어떻게 작동하는지 설명해 주셨던)이 우리에게 물려준 장기 실행 시뮬레이션 코드의 출력을 가져오라고 요청했습니다.

몇 가지 작은 테스트를 실행했는데 모든 것이 잘 작동했습니다. 그런 다음 약 한 달 전에 전체 시뮬레이션을 시작했고 그 이후로 지속적으로 실행해 왔습니다. 그러나 불과 몇 분 전에 일부 메모리 문제로 인해 포맷된 테이블 출력을 디스크에 쓰기 전에 프로그램이 충돌했습니다.

다행히 중간 결과의 터미널 에코를 활성화하고 롤백 기록을 큰 값으로 설정했습니다. 롤백 모드로 전환하고 전체 터미널 덤프를 텍스트 파일에 복사하고 백업 복사본을 만들어 출력의 일부를 복구했습니다.

이제 이 터미널 출력은 매우 장황합니다(디버깅 목적으로 의도적으로 그렇게 함). 아래는 복구된 터미널 출력 텍스트 파일의 스냅샷입니다(라고 부르겠습니다 terminal_output.txt).

1 Linear search iteration no. 1 begins: Attempting to blah blah with 1 ...
2 blah blah 
3 blah 
4 blah blah blah
5 lorem ipsum 
.........
........
75 Success with 128 blah ....
76 blah blah
77 blah blah
78 result_flag: 1, exit_reason: 6
79 blah
80 Completed optimal computation with T_init = 25.00 degC & T_sink = 35.00 degC

그러면 이 정확한 패턴이 반복됩니다. 예를 들어,

81 Linear search iteration no. 2 begins: Attempting to blah blah with 1 ...
82 blah
......
95 Success with 307 blah ....
......
......
100 Completed optimal computation with T_init = 30.00 degC & T_sink = 40.00 degC

내 요구 사항은 다음 정보를 추출하여 다음과 같은 표 형식 출력을 생성하는 것입니다.

25  35  128
30  40  307
...........
...........

T_init즉, 첫 번째 열과 두 번째 열은 각각 과 에 해당하는 값에서 , T_sink로 시작하는 행에서 나옵니다 Completed. 세 번째 열은 처음부터의 행 값입니다( 도움이 된다면 Success항상 5행 앞으로 ). Completed열 사이에는 공백, 탭, 쉼표 등 모든 구분 기호가 허용됩니다.

grep, 심지어 sed와 같은 표준 *nix 유틸리티를 사용하여 awk로컬에서 이 작업을 수행 하고 싶습니다 vi/vim. 파이프라인으로 연결된 단일 라인이나 bash함께 연결된 스크립트가 작동합니다. 필요하다면 다른 스크립트 언어 python도 사용할 의향이 있습니다.perl

답변1

본질적으로 원하는 부분을 캡처하고 원하지 않는 부분을 폐기하는 문제입니다. 예를 들어, sed정수 값을 캡처 하고 (를 사용하여 Success예약된 공간에 복사 할 수 있습니다.시간), 검색하고 추가합니다(G)를 다음 줄에 캡처된 번호로 변환합니다 Completed.

sed -nE \
  -e '/Success/ {s/.* ([0-9]+).*/\1/; h;}' \
  -e '/Completed/{G; s/.*T_init = ([0-9]+)\.00 degC & T_sink = ([0-9]+).*\n/\1 \2 /; p;}
' terminal_output.txt

Perl은 IMHO가 더 읽기 쉬운 표현이 풍부한 구문을 제공합니다.

perl -lne '
  our $a = $1 if /Success.*?(\d+)/; print join " ", /(\d+)\.\d+/g, $a if /Completed/
' terminal_output.txt

원하는 출력을 생성

25 35 128
30 40 307

답변2

POSIX 호환 sed:

grep -e 'Success' -e 'Completed' your_file | sed 'N;s/Success with \([[:digit:]]\+\).*T_init = \([^[:space:]]\+\).*T_sink = \([^[:space:]]\+\).*/\2 \3 \1/;s/\.00//g'

GNU sed: (적어도 CentOS의 4.2.2에서는 일치하지 않습니다 .)\n

grep -e 'Success' -e 'Completed' your_file | sed 'N;s/Success with \([[:digit:]]\+\).*\n.*T_init = \([^[:space:]]\+\).*T_sink = \([^[:space:]]\+\).*/\2 \3 \1/;s/\.00//g'

Success및가 포함된 행을 잡고 Completed두 행(필요한 것보다 더 명시적)에 대해 작업하여 관심 있는 세 필드를 꺼내어 하나의 행으로 정렬합니다.

이렇게 하면 중요한 소수 부분( 여전히 단일 후행 0이 있는 .00것과 같은 항목 포함)을 유지하면서 모든 숫자가 잘립니다 .12.20

...Completed경고 이 줄 중 일부에 또는 가 포함되어 있으면 작동하지 않습니다.Success

답변3

빠른 awk명령을 사용하면 시작할 수 있습니다.

awk '$2 ~ /Success/{a=$4;next}; $2 ~ /Completed/{b=$8;c=$13;print a,b,c}' terminal_output.txt

Success행 앞에 여러 행이 오는 경우에는 Completed작동하지 않습니다 .

관련 정보