タブ区切りのファイルから欠落している値を含む行を削除する

タブ区切りのファイルから欠落している値を含む行を削除する

ダウンストリームプログラムで処理するタブ区切りの大容量(〜900 MB)テキストファイルがあります。値が欠落している行を削除する必要があります。各行には正しい数の列があります(したがって、欠落している値は2つのタブに対応します)。

注:私の実際のデータには約200万行と80〜300列があります。可能な文字には、az AZ 0-9 -(ハイフン)_(アンダースコア)とタブ(区切り)が含まれます。ファイルにはスペースや特殊文字はありません。

私はこの種のスクリプトに初めて触れたので、提供されたコードの説明をいただきありがとうございます。私は通常Rを使用していますが、私のファイルサイズはRのデータ操作機能を超えました。

端末(またはシェルスクリプト)から欠落している値(usingなど)を含むファイルの行を削除するにはどうすればよいですかsed

入力ファイルの例:

Col1    Col2    Col3
A        B        C
D                 F
G        H        I
J        K        

出力ファイルの例:

Col1    Col2    Col3
A        B        C
G        H        I 

答え1

そしてawk

awk -F"\t" '$1!=""&&$2!=""&&$3!=""' file

実際にははいとても簡単です。

  • awk\tフラグで指定されたフィールド区切り文字タブで入力を分割します-F。コンテンツフィールドにスペースがない場合でも、このオプションを省略できます。
  • $1!=""&&...条件です。この条件が true の場合は、awkその行を印刷します。を書くこともできますが、'$1!=""&&$2!=""&&$3!=""{print}'必須ではありません。何もしない場合、awksのデフォルトの動作はその行を印刷することです。ここで、fields$1とall$2$3空でない場合、つまり最初の3つのフィールドに値がある場合、条件はtrueです。

別のファイルに書き込むには、次のコマンドを使用します。

awk -F"\t" '$1!=""&&$2!=""&&$3!=""' input_file >output_file

編集するawk:未定義の列数の場合は、行のすべてのフィールドを確認するためにこのコマンドを使用できます。

awk -F"\t" '{for(i=1;i<=NF;i++){if($i==""){next}}}1' file

答え2

...次のいずれかを実行するには、まず次のことを行う必要があります...

t=$(printf \\t)          ### because it's hard to demo CTRL+V TAB 

...今はPOSIXを使用していますgrep...

grep -Ev "^$t+|$t($t|$)"     <in >out

grepパターンと一致しない行を選択します。| または^行ヘッダータブ、2つの連続タブ、または行末タブを$表すメタ文字 - 私が知っている限り、これは可能な唯一の失敗ケースです。

-vカソードスイッチがない場合は、次のようになります。

grep -E "([^$t]+$t){2}[^$t]" <in >out

{...タブ文字の後にタブ文字が続く文字クラスではなく、文字クラス内の1つ以上の文字で構成されるパターングループの発生回数を指定します。}()+[]^


...またはPOSIXを使用してくださいsed...

sed -ne"s/[^$t][^$t]*/&/3p"  <in >out

...または...

sed -ne"s/[^$t]\{1,\}/&/3p"  <in >out

...またはGNUまたはBSDsedシステムを使用してください...

sed -Ene"s/[^$t]+/&/3p"      <in >out

...デフォルトでは、otは、少なくとも1つのタブではなく文字で構成される可能な限り長いシーケンスの行から3番目の項目を置き換えることができない限り、行を印刷しませんsed-ns///&[^]


(移植性のためにリテラルタブを使用することをお勧めします。この回答の元のバージョンでは\バックスラッシュエスケープを使用しました。いいえ役に立つ。文字クラスでバックスラッシュエスケープを使用すると、\コードの適用性が確実に制限されます。 )[]

答え3

フィールドにスペースを含めることができない場合、空のフィールドは、最初の文字()のタブ、最後の文字()のタブ、^\tまたは\t$2つの連続したタブ文字(\t\t)を意味します。したがって、次のいずれかを含む行をフィルタリングできます。

grep -Ev $'^\t|\t\t|\t$' file

空白があると、状況がより複雑になります。フィールドが空白で始まる場合は、次を使用します(空白のみのフィールドは空白と見なされます)。

grep -Pv '\t\s*(\t|$)|\t$|^\t' file

この変更は、タブ文字、ゼロ個以上のスペース、他のタブ文字、または行末と一致する行をフィルタリングします。

最後のフィールドにスペースのみが含まれていても失敗します。これを回避するには、perlおよび-Fオプションを使用して-a入力を配列に分割し、フィールドの@F1つが空でない場合は印刷するように指示します(/^$/)。

perl -F'\t' -lane 'print unless grep{/^$/} @F' file

答え4

次のように試すことができます。

grep "^[a-zA-Z0-9]\+[[:space:]][a-zA-Z0-9]\+[[:space:]][a-zA-Z0-9]\+$" input_file > output_file

目的grepは、1つ以上のファイルで指定されたパターンに一致する文字列を見つけることです。ここで、パターンは、[a-zA-Z0-9]\+1 つ以上の英数字の後にスペースまたはタブ文字が続くものと一致します。行の先頭と一致し^、一方$は行の終わりを表します。列に別の文字が使用される場合は、上記の文字クラスに追加する必要があります。最後に、>一致する出力が出力ファイルにリダイレクトされます。

また、潜在的な落とし穴と代替ソリューションについては、以下の@terdonのコメントをご覧ください。 Linux / Unix環境で作業している場合、その有用性はgrepこの特定のソリューションをはるかに超えています。

関連情報