Shell-Script

從製表符分隔的文件中刪除缺少值的行

  • December 27, 2015

我有一個大的(~900MB)製表符分隔的文本文件,我將在下游程序中處理它。我需要刪除任何缺少值的行。每行都有正確的列數(因此缺失值對應於 2 個選項卡)。

注意:我的實際數據有大約 200 萬行和 80-300 列。可能的字元是 az AZ 0-9 -(連字元)_(下劃線)和製表符(分隔)。文件中沒有空格或特殊字元。

我是這種腳本的新手,因此對所提供的任何程式碼的解釋將不勝感激。我通常使用 R,但我的文件大小已經超出了 R 的數據操作功能。

如何在終端(或在 shell 腳本中)從文件中刪除缺少值的行(例如使用sed)?

範例輸入文件:

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

範例輸出文件:

Col1    Col2    Col3
A        B        C
G        H        I 

awk

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

其實就是這麼簡單。

  • awk在使用標誌\t指定的欄位分隔符選項卡處拆分輸入。-F當您的內容在欄位中沒有空格時,這也可以省略。
  • $1!=""&&...是一個條件。當此條件為真時,awk只需列印該行。你也可以寫'$1!=""&&$2!=""&&$3!=""{print}',但這不是必須的。當沒有給出任何動作時,awks 的預設行為是列印該行。$1在這裡,當 fields和all 不為空時,該條件為真$2$3因此目前 3 個欄位具有值時。

要寫入另一個文件,請使用:

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

…要使以下任何一項起作用,您必須首先…

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

…現在,使用 POSIX grep

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

grep將選擇與模式不匹配的行 - 它使用| or元字元來表示^行頭製表符,或兩個連續製表符,或$行尾製表符 - 這是唯一可能的失敗情況,如我可以告訴。

如果沒有-v否定開關,它可能是:

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

…它指定字元類中一個或多個字元的模式組的{出現計數,這些字元不是製表符,後跟製表符。}``(``)``+``[``]``^


…或使用 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

… where預設情況下sed-n列印任何行,除非它可以用至少一個非製表符的最長可能序列的行上的第三次出現s///代替它自己。&``[^``]


(為了可移植性,應該首選使用文字標籤。這個答案的原始版本使用了\反斜杠轉義,它沒有幫助。絕對在字元類中使用\反斜杠轉義會限制程式碼的適用性。)[``]

引用自:https://unix.stackexchange.com/questions/250853