7

ペアのファイルに対して実行しているawkスクリプトがあります。私はそれをこのように呼んでいます:

awk -f script.awk file1 file2

script.awkは次のようになります。

BEGIN {FS=":"}
{ if( NR == 1 )
    { 
      var=$2
      FS=" "
    }
   else print var,"|",$0
}

各ファイルの最初の行はコロンで区切られています。1行おきに、デフォルトの空白ファイルの区切り文字に戻す必要があります。

これは最初のファイルでは正常に機能しますが、BEGINブロックは1回しか処理されないため、各ファイルの後にFSリセットされないため失敗します。:

tldr:渡すファイルごとにawkにBEGINブロックを1回処理させる方法はありますか?

重要な場合に備えて、これをcygwinbashで実行しています。

4

4 に答える 4

11

gawkバージョン4以降を使用している場合は、BEGINFILEブロックがあります。マニュアルから:

BEGINFILEとENDFILEは、各コマンドライン入力ファイルの最初のレコードを読み取る前、および各ファイルの最後のレコードを読み取った後に本体が実行される追加の特殊パターンです。BEGINFILEルール内では、ファイルを正常に開くことができた場合、ERRNOの値は空の文字列になります。それ以外の場合は、ファイルに問題があり、コードはnextfileを使用してスキップする必要があります。それが行われない場合、gawkは開くことができないファイルに対して通常の致命的なエラーを生成します。

例えば:

touch a b c
awk 'BEGINFILE { print "Processing: " FILENAME }' a b c

出力:

Processing: a
Processing: b
Processing: c

編集-よりポータブルな方法

DennisWilliamsonが指摘しているようFNR == 1に、スクリプトの最初で同様の効果を得ることができます。これに加えてFS、コマンドラインから直接変更することもできます。例:

awk -f script.awk FS=':' file1 FS=' ' file2

ここで、FS変数は以前の値を保持します。

于 2012-09-13T15:41:22.100 に答える
5

それ以外の:

BEGIN {FS=":"}

使用する:

FNR == 1 {FS=":"}
于 2012-09-13T16:02:27.783 に答える
3

変数はあなたのFNRためにトリックをするはずです。これは、ファイル内でスコープが設定されていることを除いて同じNRであるため、入力ファイルごとに1にリセットされます。

http://unstableme.blogspot.ca/2009/01/difference-between-awk-nr-and-fnr.html
http://www.unix.com/shell-programming-scripting/46931-awk-different-between -nr-fnr.html

于 2012-09-13T15:43:46.017 に答える
0

POSIX準拠のバージョンが必要な場合は、次のことを行うのが最善です。

(FNR == 1) { FS=":"; $0=$0 }

これは、ファイルレコード番号(FNR)が1に等しい場合、フィールドセパレータをリセットすることを示していますFS$0ただし、他のすべてのフィールドとNF組み込み変数の値を再解析してリセットする必要もあります。

これは、レコード区切り文字( )が変更されないBEGINFILE場合に限り、GNUawk4.xと同等です。RS

于 2018-10-08T15:09:41.030 に答える