cutコマンドのフィールドオプションに変数を渡す方法(bash)

cutコマンドのフィールドオプションに変数を渡す方法(bash)

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.txtdatamashを使用してそれを処理する例を実行しました。

$ 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」という列を印刷します。

関連情報