awkのフルルックモード?

awkのフルルックモード?

sedawk、またはperl -n入力処理などのツール記録一度、記録存在するワイヤー基本的に。

awkwith RS、 GNU sedwith -zperlwith などの一部では、-0ooo別のレコード区切り文字を選択してレコードの種類を変更できます。

perl -n入力全体(複数のファイルを渡す場合は個々のファイル)を1つのファイルにすることができます。記録オプションがある場合-0777(または-00377より大きい8進数が続き、777が標準です)、それは彼らが言うものです。喫煙モード

awkまたは他のメカニズムを使用してRS同様の操作を実行できますか?それぞれawkを扱う文書内容は順番ではなく順番に並んでいます。ワイヤーファイルごとに?

ベストアンサー1

単一文字でawk処理するか(既存の実装と同様)正規表現で処理するか(likeまたはdo)に応じて、さまざまなアプローチをとることができます。空のファイルはスキップする傾向があるため、考慮するのは難しいです。RSawkgawkmawkawk

gawk、またはmawk正規表現になる可能性がある別のawk実装ですRS

これらの実装では、(一部のmawkオペレーティングシステム(Debianなど)は代わりに非常に古いバージョンをリリースします。@ThomasDickeyが管理する最新バージョン)、RS単一文字が含まれている場合はレコード区切り文字は対応する文字で、空の場合はawk段落モードに入りRSRSそれ以外の場合は正規表現として処理されます。

解決策は、一致しない正規表現を使用することです。一部は、x^または$xx開始前または終了後)が好きです。しかし、一部は(特にgawk)他のものよりも高価です。これまで、私はこれが^$最も効果的な方法であることがわかりました。空の入力のみが一致できますが、一致するものはありません。

だから私たちはこれを行うことができます:

awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...

ただし、空のファイルをスキップしたことに注意してください(反対perl -0777 -n)。 GNUはawkコードをステートメントに入れることでENDFILEこの問題を解決できます。ただし、BEGINFILEステートメントでもこれをリセットする必要があります$0。それ以外の場合は、空のファイルを処理した後にリセットされません。

gawk -v RS='^$' '
   BEGINFILE{$0 = ""}
   ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...

伝統的なawk実装、POSIXawk

これはただ1文字で、/もRSなく、変数もなく、通常NUL文字を処理できません。BEGINFILEENDFILERT

RS='\0'とにかく、NULバイトを含む入力を処理できないため、使用すると動作すると思うかもしれませんが、そうではありません。RS='\0'従来の実装ではとして扱われますRS=。これが短絡モードです。

1つの解決策は、入力に見つからない文字(たとえば)を使用することです\1。マルチバイト文字ロケールでは、$'\U10FFFE'UTF-8ロケールの文字など、割り当てられていない文字や非文字を形成するため、発生しないバイトシーケンスに設定することもできます。しかし、それは完璧な方法ではなく、空のファイルに問題があります。

別の解決策は、入力全体を変数に格納し、最後のEND文で処理することです。つまり、一度に1つのファイルしか処理できません。

awk '{content = content $0 RS}
     END{$0 = content
       printf "%s: <%s>\n", FILENAME, $0
     }' file

これは次のとおりですsed

sed '
  :1
  $!{
   N;b1
  }
  ...' file1

このアプローチのもう1つの問題は、ファイルが改行文字で終わらず空でない場合は、$0ファイルがまだ最後にランダムに追加されることです(上記のコードでは代わりにgawk使用できます)。 1つの利点は、/にファイルの行数を記録することです。RTRSNRFNR

一度に複数のファイルを処理するには、単一のステートメントからすべてのファイルを手動で読み取ることですBEGIN(ここでは、70年代のAPIを使用するSolarisawkではなくPOSIXを想定しています)。/bin/awk

awk -- '
  BEGIN {
    for (i = 1; i < ARGC; i++) {
      FILENAME = ARGV[i]
      $0 = ""
      while ((getline line < FILENAME) > 0)
        $0 = $0 line "\n"

      # actual processing here, example:
      print i". "FILENAME" has "NF" fields and "length()" characters."
    }
  }' *.txt

末尾改行についても同じ警告です。このファイルの利点は、=文字を含むファイル名を処理できることです。

おすすめ記事