2500列と3000行のタブ区切りファイルがあります。ヘッダーに基づいて特定の列を抽出したいと思います。ところで、これはwhileループで行われるため、毎回異なる列名が選択されます。
ファイル形式の例:
a b c d e f g h
xy 1 2 f 21 4 5 6
qu 9 10 z 50 12 7 8
希望の出力:
a b c d g
xy 1 2 f 5
qu 9 10 z 7
列番号を識別し、その番号を変数として保存し、-fの下のカットに渡すつもりです。たとえば、「g」列を選択した場合、これは7番目のフィールドです。
colNum=$(head -1 file.txt | tr '\t' '\n' | cat -n | grep "g" | cut -f 1)
cut -f1,2,3,4,"$colNum" file.txt > new_file.txt
次のエラーが発生します。
cut: fields and positions are numbered from 1
Try 'cut --help' for more information.
答え1
コメントでは、回答を含める必要はないことに同意しましたcut
。私はGNU Datamash(https://www.gnu.org/software/datamash/)はこの問題をエレガントに解決します。
問題のサンプル入力をというファイルに入れて、data.txt
datamashを使用してそれを処理する例を実行しました。
$ datamash -HW cut a,b,c,d,g < data.txt
cut(a) cut(b) cut(c) cut(d) cut(g)
xy 1 2 f 5
qu 9 10 z 7
ヘッダーにジョブ名を追加したくない場合は、一部の後処理で少しクリーンアップできます。
$ datamash -HW cut a,b,c,d,g < data.txt | sed 's/cut(\([^[:space:]]*\))/\1/g'
a b c d g
xy 1 2 f 5
qu 9 10 z 7
答え2
「cut」コマンドを使用して、タブ区切りのファイルから特定の列を抽出できます。これを行うには、目的の列の列番号を決定し、cutコマンドの「-f」オプションを使用して列番号を指定する必要があります。たとえば、ファイルから「g」列を抽出するには、次のコマンドを使用できます。
colNum=$(head -1 file.txt | tr '\t' '\n' | cat -n | grep "g" | cut -f 1)
cut -f1,2,3,4,"$colNum" file.txt > new_file.txt
最初のコマンドは、目的の列の列番号を識別します。
colNum=$(head -1 file.txt | tr '\t' '\n' | cat -n | grep "g" | cut -f 1)
2番目のコマンドは、 "cut"コマンドを使用してファイルから指定された列を抽出します。
-f1,2,3,4,"$colNum" file.txt > new_file.txt を切り捨てます。
ファイルから必要な列を抽出し、new_file.txtに保存する必要があります。 "cut"コマンドの詳細については、次の公式ドキュメントを参照してください。https://linux.die.net/man/1/cut。
私が知っている限り、あなたが見ているエラーメッセージは、cutコマンドがフィールド引数を数値として期待していますが、変数を渡していることを示します。この問題を解決するには、変数が文字列ではなく数値として解釈されるように、cutコマンドから「$ colNum」の周りの引用符を削除します。
変更されたコマンドは次のとおりです。
cut -f1,2,3,4,$colNum file.txt > new_file.txt
あるいは、awkコマンドを使用して、ヘッダーに基づいて特定の列を抽出することもできます。
awk -v col="g" -F'\t' 'NR==1{for(i=1;i<=NF;i++){if($i==col){c=i;break}}} {print $1,$2,$3,$4,$c}' file.txt > new_file.txt
このコマンドは、最初の行で列タイトル「g」を探し、変数「c」に列番号を格納し、new_file.txtで最初の4列と「g」という列を印刷します。