あるファイルの列を別のファイルの最後の列として追加

あるファイルの列を別のファイルの最後の列として追加

テキストファイルの特定の列(私の場合は列4)が新しいテキストファイルの最後の列として追加されるループを作成したいと思います。 4番目の列をインポートし、新しいテキストファイル(タブで区切られた列)に追加したい合計500個のテキストファイル(V1-V500)があります。すべてのテキストファイルの行数は同じです。さらに、追加された列のヘッダーには、その列が最初に指定されたテキストファイルのファイル名を含める必要があります。私はawkとforループを使ってコマンドラインを設定してみましたが、どのコマンドも機能しません。以前のコマンドラインに基づいてコマンドラインを試しました。郵便はがき。私は利用可能なGNUツールを使用してLinuxで作業しています。

例: V1 テキストファイル

header1 header2 header3 header4
1       5       9       13 
2       6       10      14
3       7       11      15
4       8       12      16

V2テキストファイル:

header1 header2 header3 header4
17       25       21      29 
18       26       22      30
19       27       23      31
20       28       24      32

新しいテキストファイル:

V1 V2
13 29
14 30
15 31
16 32

ご協力ありがとうございます!

答え1

awkすべてのファイルを解析します。

awk -F'\t' -v OFS='\t' '{
        x = (FNR==1 ? FILENAME : $4)
        a[FNR] = (FNR==NR ? x : a[FNR] OFS x)
    } 
    END {
        for (i=1;i<=FNR;i++) print a[i]
    }' V{1..500}

xaこれは私たちが構築するすべてのラインと新しいラインにつながるものです。どちらも割り当てを使用します。条件式FNR現在の入力ファイルの行番号とNR総行数。FNR==NR「最初のファイルを解析するとき」を意味します。また、タブで区切られた入力と出力を想定しました。

答え2

非 awk ソリューション:

#!/bin/bash
for num in {1..500}; do
        echo V$num > temp_$num #put the filename as header
        < V$num tail -n+2 | cut -f4 >> temp_$num #get the contents of column 4
        if [[ -f V_new ]]; then #if not first iteration
                paste V_new temp_$num > temp #combine previous files with current file
                mv temp V_new
        else # if first iteration
                mv temp_$num V_new 
        fi
done

答え3

awkや他のツールを使ってこれを行うことができますが、ここではより簡単なアプローチをお勧めします。

$ printf 'paste ' > script
$ printf "<(awk 'NR==1{print FILENAME; next}{print \$4}' %s) \\\\\n" V{1..500} >> script
$ sh ./script

これにより、pasteファイルにscript次のような複雑なコマンドが生成されます。

$ head script 
paste <(awk 'NR==1{print FILENAME; next}{print $4}' V1) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V2) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V3) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V4) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V5) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V6) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V7) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V8) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V9) \
<(awk 'NR==1{print FILENAME; next}{print $4}' V10) \

したがって、scriptawkコマンドを使用して実行が実行され、500個の入力ファイルのそれぞれの4番目の列が抽出されます。paste例の2つのファイルを使用すると、次のものが生成されます。

$ printf 'paste ' > script
$ printf "<(awk 'NR==1{print FILENAME; next}{print \$4}' %s) \\\\\n" V* >> script
$ sh ./script
V1  V2
13  29
14  30
15  31
16  32

答え4

awkを使用してforループに貼り付けたソリューション:

  1. 最初のファイルの列4を作成します(ファイル名をヘッダーとして使用)NEW
awk -F'\t' 'NR==1{print FILENAME; next} {print $4}' V1 > NEW
  1. NEWforループに別のファイル(ファイル名をヘッダーとして使用)の列4を追加します。一時ファイル(temp)を使用して出力を収集し、その内容を各NEW反復に移動します。
for file in V{2..500}; do
paste NEW <(awk -F'\t' 'NR==1{print FILENAME; next} {print $4}' $file) > temp && mv -f temp NEW
done

関連情報