awk와 grep 및 추출할 파일의 신호 라인을 비교하는 모범 사례

awk와 grep 및 추출할 파일의 신호 라인을 비교하는 모범 사례

여러 파일이 포함된 폴더가 있습니다. .txt이 파일의 내용을 기반으로 세 개의 새 파일을 만들고 싶습니다 . 이를 달성하기 위해 3개의 새 문서를 만드는 데 사용할 파일의 다른 부분을 표시하는 begin/ 태그를 만들어야 한다고 생각했습니다 .end

예를 들어 첫 번째 파일의 구조 01_FileName.mac는 다음과 같습니다.

/* 01_FileName */

/* START HEADER */
 Header 1 Content
/* END HEADER */

/* START SCRIPT */
    Script 1 Content
/* END SCRIPT */

/* START COMMENTS */
    Comments 1 Content
/* END COMMENTS */

마찬가지로 두 번째 입력 파일은 다음과 같습니다 02_FileName.mac.

/* 02_FileName */

/* START HEADER */
 Header 2 Content
/* END HEADER */

/* START SCRIPT */
    Script 2 Content
/* END SCRIPT */

/* START COMMENTS */
    Comments 2 Content
/* END COMMENTS */

해당 파일이 2개 이상 있다는 점에 유의하세요.

다음 세 가지 새 문서를 만들고 싶습니다.

  1. Concatenated_Header.txt:

    Header 1 Content
    Header 2 Content
    
  2. Concatenated_Script.txt:

     Script 1 Content
     Script 2 Content
    
  3. Concatenated_Load_Commands.txt:

    push("<NameOfCurrentPath>")$
       load("<NameOfCurrentPath>/01_FileName.mac")$
       load("<NameOfCurrentPath>/02_FileName.mac")$
    

특정 줄이나 특정 문자열을 연결하는 것과 관련된 예제를 본 적이 있지만, 부분을 새로운 개별 파일로 결합하기 위해 start나누고 합하는 일반적인 방법은 아닙니다.end

참고: 파일의 정확한 구조는 실제로 중요하지 않습니다. 이러한 부분( , 및 )을 내보내는 데 도움이 되는 문서 fileName구조 는 괜찮습니다 . 목표는 스크립트와 관련된 모든 정보를 단일 파일에 저장하면서 이 세 개의 새 파일을 생성하는 것입니다. 이것이 바로 제가 라벨을 사용하여 이 프로세스를 용이하게 할 수 있다고 상상한 방식입니다.Header ContentScript ContentComments Contentstartend

(이것을 봐주세요초기 개정더 많은 배경과 세부사항을 보려면)

답변1

awk 'function prnt(type, pr){ print pr >"concatenated_"type".txt"; };
     FNR==1{ type="load";
             if (!path) {
                 path=FILENAME; sub("[^/]+$","",path);
                 prnt(type, "push(\"<"path">\")$");
              };
              prnt(type,"\tload(\"<"FILENAME">\")$");
           };
     /START HEADER/{ prn=1; type="header"; next; };
     /START SCRIPT/{ prn=1; type="script"; next; };
     /END SCRIPT/ || /END HEADER/{ prn=0; };
prn{ prnt(type, $0); }' /home/User/Unix/*.mac

우리는Function; prnt은 이름이며 두 개의 인수를 사용합니다. 하나는 짧은 문자열을 가져와 pr인수의 출처에서 줄을 작성해야 하는 출력 파일 이름의 일부로 사용합니다.

function prnt(type, pr){ print pr >"concatenated_"type".txt"; }

매개변수 type값은 조건부로 변경되는데, input 의 첫 번째 줄이면 파일 이름과 경로를 기록하도록 FNR==1설정 하지만type="load"if(!path) { path=FILENAME; ...; }한 번만 작성해야 하므로 한 번만 작성되도록 했습니다 . 다음 번에는 path변수에 이미 값이 있으므로 if 문의 블록이 실행되지 않습니다.다시 분리됨) 나머지 입력에서는 파일 이름과 각 파일을 FNR==1.

행에 가 포함되어 있는지 설정 /START HEADER/하고 그에 따라 ; type="header"또한 제어 변수 플래그를 사용하여 개인 파일 이름에 줄을 인쇄하기 위해 함수가 호출되는 시기를 제어합니다.type="script"/START SCRIPT/prn=1prn{ prnt(type, $0); }

next명령은 다시 시작하고 입력의 다음 줄을 읽는 데 사용되므로 다음 명령을 계속하거나 쓰지 않습니다.타이틀 출발선출력의 라인 자체.

또한 prn=0인쇄를 방지하기 위해 플래그를 재설정합니다.머리부터 꼬리까지철사.

답변2

$ cat tst.awk
BEGIN {
    out["HEADER"] = "Concatenated_Header.txt"
    out["SCRIPT"] = "Concatenated_Script.txt"
    out["LOAD"]   = "Concatenated_Load_Commands.txt"
}

FNR == 1 {
    if ( NR == 1 ) {
        dir = FILENAME
        sub("/[^/]+$","",dir)
        printf "push(\"%s\")$\n", dir > out["LOAD"]
    }
    printf "   load(\"%s\")$\n", FILENAME > out["LOAD"]
}

block {
    if ( index($0,"/* END ") == 1 ) {
        block=""
    }
    if ( block in out ) {
        print > out[block]
    }
    next
}

index($0,"/* START ") == 1 { block=$3; next }

$ awk -f tst.awk $PWD/*.mac

$ head Concat*
==> Concatenated_Header.txt <==
 Header 1 Content
 Header 2 Content

==> Concatenated_Load_Commands.txt <==
push("/home/foo/tmp")$
   load("/home/foo/tmp/01_FileName.mac")$
   load("/home/foo/tmp/02_FileName.mac")$

==> Concatenated_Script.txt <==
    Script 1 Content
    Script 2 Content

out["COMMENTS"] = "Concatenated_Comments.txt"주석의 출력 파일도 생성하려면 해당 섹션에 한 줄을 추가하면 됩니다 BEGIN. 귀하가 만드는 다른 콘텐츠도 마찬가지입니다 START. .. END조각 . 스크립트는 /* START블록의 외부와 내부 만 검색하며 /* END둘 다 줄의 시작 부분에서만 검색하므로 이러한 문자열은 스크립트를 손상시키지 않고 텍스트 블록에 나타날 수 있습니다.

관련 정보