한 파일의 열을 다른 파일의 마지막 열로 추가

한 파일의 열을 다른 파일의 마지막 열로 추가

텍스트 파일의 특정 열(내 경우에는 열 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예제의 두 파일을 사용하면 다음이 생성됩니다.

$ 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

관련 정보