回答:
別のPOSIXの1つ:
awk -F , 'NF == 11' <file
行に10個のコンマがある場合、この行には11個のフィールドがあります。したがって、単にフィールド区切り文字としてawk
使用,
します。フィールド数が11の場合、条件NF == 11
はtrueでありawk
、デフォルトのアクションを実行しますprint $0
。
-F
フィールドセパレーターを設定NF
し、指定された行のフィールド数を参照します。{statement}
条件NF == 11
にコードブロックは追加されないため、デフォルトのアクションは行を印刷することです。(@cuonglm、必要に応じてこの説明を自由に組み込んでください。)
awk -F , 'NF != 11' <file
-
や名前が付けられたファイルから保護します-
。
使用egrep
(またはgrep -E
POSIX):
egrep "^([^,]*,){10}[^,]*$" file.csv
これは、10個のコンマを含まないものをすべて除外します。これは、「「、」を除く任意の数の文字、その後に単一の「、」を含む」シーケンスの正確な10回の繰り返し()を含む完全な行(^
最初と$
最後)に一致します。{10}
(([^,]*,)
)の後に、 '、'([^,]*
)を除く任意の数の文字が続きます。
-x
パラメータを使用してアンカーを削除することもできます。
grep -xE "([^,]*,){10}[^,]*" file.csv
ただし、これはcuonglmのawk
ソリューションよりも効率的ではありません。後者の場合、私のシステムでは、コンマが約10行ある場合、通常6倍速くなります。ラインが長いと、速度が大幅に低下します。
機能する最も単純なgrep
コード:
grep -xE '([^,]*,){10}[^,]*'
説明:
-x
パターンは、ラインの一部ではなく、ライン全体と一致する必要があります。これは重要であり、コンマが10個を超える行を照合しないでください。
-E
「拡張正規表現」を意味します。これにより、正規表現でのバックスラッシュエスケープが少なくなります。
括弧はグループ化に使用され、{10}
その後は、括弧内のパターンの行に正確に10個の一致がなければならないことを意味します。
[^,]
文字クラス-のインスタンスは、されて[c-f]
いる任意の単一文字一致しc
、A d
、e
またはf
、そして[^A-Z]
大文字ではありません任意の単一文字に一致します。したがって[^,]
、カンマを除く任意の1文字に一致します。
*
文字クラスの後は、「これらのゼロ以上」を意味します。
したがって、regexの部分([^,]*,)
は「コンマを除いた任意の文字(ゼロ回を含む)を何回でも続けてコンマを続ける」を意味し{10}
、これらのうち10個を指定します。次に[^,]*
、残りの非コンマ文字を行末に一致させます。
sed -ne's/,//11;t' -e's/,/&/10p' <in >out
まず、11個以上のコンマを含む行を分岐し、次に、10個のコンマと一致するものだけを残して出力します。
どうやら私は以前にこれに答えたようです... いくつかのパターンの正確な4つの発生を探す質問からの盗用です:
コマンドにを追加するだけ
[num]
で、seds///
ubstitutionコマンドでパターンの出現をターゲットにでき[num]
ます。t
置換の成功を予測し、ターゲット:
ラベルを指定しない場合、t
estはスクリプトから分岐します。つまり、必要なのは、1s///5
つ以上のカンマをテストして、残っているものを出力することだけです。または、少なくとも、最大4を超える行を処理します。どうやら、最小要件もあるようです。幸いなことに、それは同じくらい簡単です。
sed -ne 's|,||5;t' -e 's||,|4p'
...
,
行の4番目のオカレンスをそれ自体で置き換えp
、s///
ubstitutionフラグにリントを追加します。,
5回以上一致する行はすでに整理されているため、4つの,
一致を含む行には4つしか含まれていません。
sed
awk
参照して- 私はこの回答を気に入って賛成しましたが、受け入れられたawk
回答の翻訳は「11フィールドの行を印刷する」であり、このsed
回答の翻訳は: 11番目のコンマを削除してみてください。失敗した場合は次の行にスキップしてください。10番目のコンマをそれ自体に置き換えてみてください。成功した場合は行を印刷してください。」awk
その答えは、コンピュータへの命令にあなたが英語でそれらを表現するのと同じ方法を提供します。(awk
フィールドベースのデータに適しています。)
そして、これがPerlの方法です:
perl -F, -ane 'print if $#F==10'
-n
原因perl
によって与えられたスクリプトラインで、入力ファイルの行を読み込んで実行するために-e
各行のを。-a
自動分割をオン:各入力線は、で与えられる値に分割される-F
(ここで、カンマ)とアレイとして保存しました@F
。
$#F
(または、より一般的に$#array
)、アレイの最も高い指標です@F
。配列はから始まるため0
、11フィールドの行にはのが@F
あり10
ます。したがって、スクリプトは、フィールドがちょうど11の場合、行を出力します。
print if @F==11
スカラーコンテキストの配列が要素の数を返すようにすることもできます。
フィールドにカンマまたは改行を含めることができる場合、コードはcsv を理解する必要があります。例(3つの列):
$ cat filter.csv
a,b,c
d,"e,f",g
1,2,3,4
one,two,"three
...continued"
$ cat filter.csv | python3 -c 'import sys, csv
> csv.writer(sys.stdout).writerows(
> row for row in csv.reader(sys.stdin) if len(row) == 3)
> '
a,b,c
d,"e,f",g
one,two,"three
...continued"
これまでのほとんどの解決策では、2行目と4行目が破棄されると思います。
sed
ここで行うように)探しているものよりも1つだけ一致する範囲だけをスキャンする必要はありません。これを閉じるべきではありませんでした。