쉘 스크립트를 사용하여 여러 파일의 특정 문자열을 구문 분석하는 방법

쉘 스크립트를 사용하여 여러 파일의 특정 문자열을 구문 분석하는 방법

저는 esp32 프로젝트를 진행 중이며 모든 esp32 uart 디버그 출력을 여러 파일에 기록하고 있습니다. 어느 시점에서 이전 버전이 충돌하고 출력은 다음과 같습니다.

전문가 명상 오류: 코어 0에서 패닉이 발생했습니다(캐싱이 비활성화되었지만 캐시 메모리 영역에 액세스했습니다).

코어 0 레지스터 덤프: PC: 0x40008150 PS: 0x00060034 A0: 0x8008225c A1: 0x3ffb0670 A2: 0x3f40117c A3:
0x00000000 A4: 0x00000004 A5: 0x00000000
A6: 000000 0 A7: 0xffffffff7 A8: 0x00000000 A9: 0x00000000
A10: 0x000000ad A11: 0x00000000 A12: 0x800861de A13: 0x3ffbb010
A14: 0x00000003 A15: 0x00060a23 SAR: 0x00000020 이유: 0x00000007
EXCVADDR: 0x00000000 LBEG: 0x4000c2e0 대출: 0x4000 c2f 6 LCOUNT: 0x00000000
ISR 컨텍스트에서 실행되는 코어 0: EPC1: 0x4008a2e8 EPC2: 0x00000000 EPC3: 0x00000000 EPC4: 0x40008150

역추적: 0x4000814d: 0x3ffb0670 0x40082259: 0x3ffb0700 0x400833b9: 0x3ffb0720 0x400833e2: 0x3ffb0740 0x40081e6a: 0x3ffb0760 0x4008a2e 5: 0x3 ffbb0a0 0x4008438d:0x3ffbb0c0 0x400830ed:0x3ffbb0e0 0x40083271:0x3ffbb110 0x400de4b1:0x3ffbb130 0x400dd525:0x3ffbb150 0x400dd7c5:0x3ff bb170 0 x 400de175:0x3ffbb1d0 0x400dccf2:0x3ffbb240 0x400dcedf:0x3ffbb2a0 0x400dcf47 :0x3ffbb2d0 0x400dbebf:0x3ffbb2f0 0x400dbed2:0x3ffbb310 0x400d757a:0x3ffbb330 0x400d770a:0x3ffbb360 0x400d3a66:0x3ffbb380

ELF 파일 SHA256: c278c3c874dd3748

다시 시작하는 중...

이 시점에서 트레이스백이 가리키는 코드 검사를 시작할 수 있습니다.

addr2line xtensa-esp32- -pfiaC -e project.elf 0x400d3a66 0x400d770a 0x400d757a ...(the remaining addresses of the backtrace)

출력은 다음과 같습니다.

0x400d3a66: root_task는 $somePATH/build/../main/main.c:163에 있습니다.

0x400d770a: $somePATH/build/../main/init_app.c:122에서 초기화 중

0x400d757a: init_nvs_app은 $somePATH/build/../main/init_app.c:47에 있습니다.

(인라인) init_nvs_app은 /$somePATH/build/../main/init_app.c:34에 있습니다.

그것은 지루. 그래서 자동화해야 하는데 쉘 스크립트에 대한 경험이 많지 않습니다(Linux를 처음 접함).

이를 달성하는 방법도 수백만 가지가 있습니다. 경험이 있는 사람이 "마스터 명상 오류:"와 "다시 시작..." 사이의 텍스트를 파악하는 데 도움을 줄 수 있습니까? 트레이스백에서 PC(프로그램 카운터) 주소를 한 줄로 분리하고 SP(스택)를 무시하는 가장 좋은 방법은 무엇입니까? 포인터)(이 특별한 경우 SP 주소는 0x3ff로 시작합니다). grep regex와 awk로 몇 가지를 시도했지만 충분하지 않습니다.

답변1

sed버전:

sed -n -E -e '/^Backtrace:/ {s/Backtrace://; s/:0x3ff[^ ]* */ /g; p}' input.txt

이는 "Backtrace:"로 시작하지 않는 모든 줄을 무시하고 두 개의 검색 및 바꾸기 규칙을 사용하여 출력을 인쇄하기 전에 일치하는 줄을 수정합니다.

s/:0x3ff[^ ]* */ /g작업은 다음으로 시작하고 그 :0x3ff뒤에 0개 이상의 공백이 아닌 문자( [^ ]*)가 오고 그 뒤에 0개 이상의 공백( *)이 오는 모든 텍스트를 일치시키고 발견된 일치 항목을 단일 공백 ​​문자로 바꿉니다. 전역 검색 및 바꾸기( /g)이므로 영향을 미칩니다.모두첫 번째 일치 항목뿐만 아니라 온라인에서 찾은 일치 항목입니다.

"Guru Meditation" 및 "Reboot"에 대한 작업을 제한하려고 시도하지 않습니다. 입력에 "Backtrace:"로 시작하는 다른 줄이 없거나 한 번에 하나의 입력 파일만 제공되는 경우 이 방법으로 충분합니다.

여러 실행에서 일정하지 않은 경우 콜론과 1개 이상의 16진수 숫자가 뒤따르는 정규식 0x3ff으로 변경할 수 있습니다 . 0x예를 들어

s/:0x[0-9a-f]+//gi

이 변경 사항은 원하는 경우 기본 awk 및 Perl 버전에서도 작동합니다.

awk버전:

awk -v SKIP=1 '/^Guru Meditation Error/ { SKIP=0 };
               /^Rebooting\.\.\./ { SKIP=1} ;
               SKIP==1 || ! /^Backtrace:/ { next };
               {
                   sub("^Backtrace:","");
                   gsub(":0x3ff[^ ]* *"," ");
                   print
               }
              ' input.txt

이는 "Guru Meditation"과 "Rebooting" 줄 사이에 없는 모든 입력과 "Backtrace:"로 시작하지 않는 모든 입력을 건너뜁니다. 그런 다음 수정된 줄을 인쇄하기 전에 sub()건너뛰지 않은 줄을 수정하기 위해 두 가지 검색 및 바꾸기 작업(및) 을 사용합니다.gsub()

진주 버전:

perl -lne 'BEGIN {$SKIP=1};
           $SKIP=0 if (m/^Guru Meditation Error/);
           $SKIP=1 if (m/^Rebooting\.\.\./);
           next if ($SKIP || ! m/^Backtrace:/);
           s/Backtrace://;
           s/:0x3ff\H*\h*/ /g;
           print' input.txt

이는 awk 버전과 유사하게 작동하지만 코드는 awk와 sed 버전 사이의 교차처럼 보입니다(perl은 awk 유사 및 sed 유사 구문 등이 가능합니다).

최종 작업은 공백(예: 탭 및 공백 등)뿐만 아니라 Perl (비수평 공백 문자) 및 (수평 공백 문자) 일치를 s//g사용하도록 수정되었습니다. 자세한 내용은 "공백" 섹션을 참조하고 검색하세요.\H\hman perlrecharclass

세 가지 버전 모두의 출력은 동일합니다.

0x4000814d 0x40082259 0x400833b9 0x400833e2 0x40081e6a 0x4008a2e5 0x4008438d 0x400830ed 0x40083271 0x400de4b1 0x400dd525 0x400dd7c5 0x400de175 0x400dccf2 0x400dcedf 0x400dcf47 0x400dbebf 0x400dbed2 0x400d757a 0x400d770a 0x400d3a66 

세 가지 버전 모두 표준 입력이나 명령줄의 하나 이상의 파일 이름에서 입력을 받을 수 있습니다. 위의 예에서는 사용합니다 input.txt(예제 입력을 복사하여 붙여넣은 텍스트 파일입니다).

둘 다 stdout으로 출력하므로 명령 대체에 사용할 수 있습니다. 예를 들어

addr2line xtensa-esp32- -pfiaC -e project.elf $(sed -n -E -e '/^Backtrace:/ {s/Backtrace://; s/:0x3ff[^ ]* */ /g; p}' input.txt)

관련 정보