パイプ|
区切りファイルがあります。
ファイル:
106232145|"medicare"|"medicare,medicaid"|789
各行のフィールド数を数えたいと思います。以下のコードを試しました
コード:
awk -F '|' '{print NF-1}'
これは、結果を 4 ではなく 5 として返します。これは、awk が「medicare|medicaid」を 1 つのフィールドではなく 2 つの異なるフィールドとして受け取るためです。
純粋な Unix ソリューション (awk/Perl なし):
$ cat /tmp/x1
1|2|3|34
4534|23442|1121|334434
$ head -1 /tmp/x1 | tr "|" "\012" | wc -l
4
Perl ソリューション - ワンライナー:
$ perl5.8 -naF'\|' -e 'print scalar(@F)."\n";exit;' /tmp/x1
4
しかし!!!!重要!!!
これらのソリューションはすべて、他の回答のソリューションと同様に、100%機能しません。
つまり、実際の CSV ファイルのように、パイプがフィールド (および引用符で囲まれたフィールド) で有効な文字である REAL の「パイプで区切られた」ファイルである場合、それらはすべて壊れます。
例えば
$ cat /tmp/x2
"0|1"|2|3|34
4534|23442|1121|334434
$ perl5.8 -naF'\|' -e 'print scalar(@F)."\n";exit;' /tmp/x1
5 <----- BROKEN!!! There are only 4 fields, first field is "0|1"
これを修正するには、Perl のような適切な CSV (または区切りファイル) パーサーを使用する必要があります。
$ perl5.8 -MText::CSV_XS
-ne '$csv=Text::CSV_XS->new({sep_char => "|"}); $csv->parse($_);
print $csv->fields(); print "\n"; exit;' /tmp/x2
正しい値を出力します
4
注意として、複雑な RegEx で単にawk
orsed
ソリューションを修正するのは簡単ではありません。これは、パイプを含む引用符付きの PSV フィールドに加えて、仕様ではフィールドの一部として引用符も許可されているためです。それは、優れた正規表現ソリューションには向いていません。
$ cat fieldparse.awk
#NR > 1 { print "--"; }
# Uncomment printf/print in the for loops to see
# each field on a separate line as well as the commented line above (to show that it works).
{
nfields = 0;
for (i = 1; i <= NF; i++) {
if ($i ~ /^".*[^"]$/)
for (; i <= NF && ($i !~ /.*"$/); i++) {
#printf("%s%s", $i, FS);
}
#print $i;
nfields++;
}
print nfields;
if (FILENAME == "-")
FILENAME = "(standard input)";
filenames[FILENAME] = sprintf("%d %d", FNR, nfields);
}
END {
print NR, "total records processed";
for (f in filenames) {
split(filenames[f], fn, " ");
printf("\t* %s: %d records with %d fields\n", f, fn[1], fn[2]);
}
}
$ awk -F'|' -f fieldparse.awk demo.txt
二重引用符ではない単一文字の区切り記号、つまり標準のタブ区切り、CSV などの形式 (とにかく標準として...) で機能します。
出力形式は単なる説明であり、最後に少し装飾的ですが、コンテンツは複数のファイルを処理するなど、私見でも役立ちます。いずれにせよ、それが役立つことを願っています!:-)
編集
これは、mawk と GNU awk (gawk) を使用してテストされ、後者は従来の POSIX モードとデフォルト モードでテストされました。コメントと出力ステートメントをトリミングして、実際には小さなプログラムであることがわかりますが、好きなほど小さくはありません。