awkとgrepと抽出するファイルの信号線を比較するベストプラクティス

awkとgrepと抽出するファイルの信号線を比較するベストプラクティス

複数のファイルを含むフォルダがあります。.txtこのファイルの内容に基づいて3つの新しいファイルを作成したいと思います。これを達成するために、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 */

同様に、2番目の入力ファイルは次のとおりです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つ以上あることに注意してください。

次の3つの新しい文書を作成したいと思います。

  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構造は問題ありません。目的は、スクリプトに関するすべての情報を単一のファイルに保存しながら、これら3つの新しいファイルを作成することです。これが私がラベルを使ってこのプロセスを容易にすることができると想像した方法です。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は名前で、2つの引数を使用します。 1つは、短い文字列を取得し、引数のソース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"コメントの出力ファイルも作成するには、そのセクションに1行を追加するだけですBEGIN。あなたが作る他のコンテンツも同じですSTART。 ..END彫刻 。スクリプトは/* STARTブロックの外側と内側のみを検索し、両方とも行/* ENDの先頭でのみ検索するため、これらの文字列はスクリプトを破損することなくテキストブロックに表示される可能性があります。

関連情報