ダウンストリームプログラムで処理するタブ区切りの大容量(〜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
。-n
s///
&
[^
]
(移植性のためにリテラルタブを使用することをお勧めします。この回答の元のバージョンでは\
バックスラッシュエスケープを使用しました。いいえ役に立つ。文字クラスでバックスラッシュエスケープを使用すると、\
コードの適用性が確実に制限されます。 )[
]
答え3
フィールドにスペースを含めることができない場合、空のフィールドは、最初の文字()のタブ、最後の文字()のタブ、^\t
または\t$
2つの連続したタブ文字(\t\t
)を意味します。したがって、次のいずれかを含む行をフィルタリングできます。
grep -Ev $'^\t|\t\t|\t$' file
空白があると、状況がより複雑になります。フィールドが空白で始まる場合は、次を使用します(空白のみのフィールドは空白と見なされます)。
grep -Pv '\t\s*(\t|$)|\t$|^\t' file
この変更は、タブ文字、ゼロ個以上のスペース、他のタブ文字、または行末と一致する行をフィルタリングします。
最後のフィールドにスペースのみが含まれていても失敗します。これを回避するには、perl
および-F
オプションを使用して-a
入力を配列に分割し、フィールドの@F
1つが空でない場合は印刷するように指示します(/^$/
)。
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
この特定のソリューションをはるかに超えています。