行区切り文字が %=$% (\n 文字なし) で列区切り文字が |#@| の場合、Unix で列区切り文字の数が異なる行を検索する方法は?

行区切り文字が %=$% (\n 文字なし) で列区切り文字が |#@| の場合、Unix で列区切り文字の数が異なる行を検索する方法は?

abc.txtという区切りファイルがあります。列名がカンマ(、)で区切られたヘッダー行があります。すべてのデータ行とヘッダー行に使用される行区切り文字は%=$%です(新しい行を表す改行なし)。データ行の列区切り文字は |#@| です。 Unixでデータ行に33列を持たない行を見つけるには?

答え1

Unbuntu 18 では、GNU Awk 4.1.4 を%=$%レコード区切り文字として使用できません。マクロが入っています。TXR不明瞭な音声働く

33フィールドなしでレコードを印刷する:

$ echo -n 'A,B,C,D%=$%FOO|#@|BAR%=$%X' | \
txr -e '(awk (:set rs #/\%=$\%/ fs ",")
             ((= nr 1) (set fs #/\|#@\|/) (next))
             ((/= nf 33) (prn)))'
FOO|#@|BAR
X

TXR Lispの正規表現はであり、#/.../演算子%(貪欲ではないバージョン*)なので、エスケープする必要があります。

強制的に再計算するために、フィールドリストをそれf自体に割り当てることができます。(set f f)recofs

$ echo -n 'A,B,C,D%=$%FOO|#@|BAR%=$%X' | \
txr -e '(awk (:set rs #/\%=$\%/ fs ",")
             ((= nr 1) (set fs #/\|#@\|/) (next))
             ((/= nf 33) (set f f) (prn)))'
FOO BAR
X

フィールドは[f 0][f 1]であり、レコード全体は、およびrecとは異なります。 Awkと同様に、フィールドを強制的に再計算する最も短い方法です。$1$2$0(set f f)recf$1=$1

GNU Awkで同じように動作できない理由デバッグに戻って...

知っていた:

$ echo -n 'A,B,C,D%=$%FOO|#@|BAR%=$%X' | gawk \
'BEGIN { RS="%=\\$%"; FS = "," }
 NR == 1 { FS = "\\|#@\\|" }
 NF != 33 { $1=$1; print }'
A B C D
FOO BAR
X

nextルールが欠落しているため、NR == 1ヘッダも表示されます。

awkの$正規表現の文字はエスケープする必要がありますが、RSそれは問題です。もちろん今、私はこれを不正確で混乱させようとしました。

# incorrect escaping of $
$ gawk -v RS='%=\$%' ''
gawk: warning: escape sequence `\$' treated as plain `$'

しかし、ここで私たちがすることは、正規表現として解釈される文字列を割り当てることです。 Gawkは、\$文字列リテラル構文にエスケープがないと言います。これは正しいです。しかし、私たちにとって必要なのは、ドル記号を正規表現文字でエスケープすることです。これをAwk文字列に入れるには、それをエスケープして\\から$正規表現の意味をエスケープする必要があります。

関連情報