한 파일의 인덱스 값을 사용하여 인쇄하고, 두 번째 파일에서 데이터를 추출하고, 출력을 세 번째 파일에 저장하려면 어떻게 해야 합니까?

한 파일의 인덱스 값을 사용하여 인쇄하고, 두 번째 파일에서 데이터를 추출하고, 출력을 세 번째 파일에 저장하려면 어떻게 해야 합니까?

다음과 같이 2개의 파일이 있습니다.

# File 1 has 3 columns:
SampleName   Type     Position
5R01924      ABC      92184093
5R01028      ABC      15589809
5R01092      ABC      48759348
# File 2 has many columns. 
# Column 2 is the Position 
# Columns 5 to end are the different SampleNames
A   Position   B    C    5R01924       5R01028       5R01092 
1   15589809   2    3    D:E:F:G       H:I:J:K       L:M:N:O
1   92184093   2    3    P:Q:R:S       T:U:V:W       X:Y:Z:AA
1   48759348   2    3    AB:AC:AD:AE   AF:AG:AH:AI   AJ:AK:AL:AM

첫 번째 파일에 네 번째 열을 추가하거나, 파일 1을 복사하고 이 새로운 세 번째 파일에 네 번째 열을 추가하고 싶습니다.

열 4에는 파일 1의 인덱스를 사용하여 파일 2에서 추출된 올바른 정보가 포함되어야 합니다. 따라서 파일 1의 라인 1은 파일 2의 라인 2로 이동하여 열 5(5R01924)에서 정보를 추출한다는 의미입니다. 그러나 나는 이 정보의 R 부분만 원합니다. 따라서 출력은 다음과 같아야 합니다.

# file 3 or append column 4 to file 1
SampleName   Type     Position     Output
5R01924      ABC      92184093     R
5R01028      ABC      15589809     J
5R01092      ABC      48759348     AL

지금까지 나는 다음과 같은 것을 가지고 있습니다 :

while IFS=" " read -r value1 value2 value3
do
        awk '$2 == "${value3}" {
        # find column # from name of value 1 (save as col variable) 
        print split(${col},a,":"), a[3]
        }' file2 >> file3.txt
done
# where does file 1 go? 

도와주세요:)

답변1

awk는 이를 자체적으로 처리할 수 있습니다. 여기에 "combine.awk" 파일이 있습니다.

# first file, first line
FILENAME == ARGV[1] && FNR == 1  {
    for (i=5; i<=NF; i++) head[i] = $i
}

# first file,  subsequent lines
FILENAME == ARGV[1] && FNR > 1 {
    for (i=5; i<=NF; i++) {
        split($i, f, /:/)
        value[$2, head[i]] = f[3]
    }
}

# second file
FILENAME == ARGV[2] {
    print $0, (FNR == 1 ? "Output" : value[$3, $1])
}

그러면 이렇게 부르죠

awk -f combine.awk file2 file1 > file3

출력 파일에는 다음이 포함됩니다.

SampleName   Type     Position Output
5R01924      ABC      92184093 R
5R01028      ABC      15589809 J
5R01092      ABC      48759348 AL

답변2

파일을 읽기 위해 bash를 호출할 필요가 없습니다.

우리는 이 모든 것을 awk에서 다음과 같이 할 수 있습니다:

### sanitize inputs
for f in ./File1 ./File2; do
  dos2unix "$f"
done

awk '
  !NF || $1 ~ /^#/ {next}
  NR==FNR {
    for (i=5; i<=NF; i++)
      if (NR > 1) {
        split($i, t, /:/)
        a[sample[i-4],$2] = t[3]
        split("", t, ":")
      }
      else sample[i-4] = $i
    next
  }
  {
    k = $1 SUBSEP $3
    f = FNR == 1  ? "Output" \
      : !(k in a) ? "N/A"    \
      : a[k]
    print $0, f
  }
' File2 OFS="\t" File1

산출:

SampleName   Type     Position  Output
5R01924      ABC      92184093  R
5R01028      ABC      15589809  J
5R01092      ABC      48759348  AL

답변3

첫째, 귀하의 질문은 복잡하므로 간단한 답변을 기대할 수 없습니다.

awk 'BEGIN{IFS="[[:space:]]+";OFS=" ";} NR>1 && NR==FNR {Trr[$3]=$0;Arr[$1]=$3;next} NR>FNR && FNR==1 {for(key in Arr) {for(i=5;i<=NF;i++) {if(key==$i) {nArr[key]=i;break}}}} NR>FNR && FNR>1 {for(tKey in Trr) {if($2==tKey) {for(aKey in Arr) {if(Arr[aKey]==$2) {i=nArr[aKey];Trr[tKey]=Trr[tKey]" "$i;break}}}}}END{for(key in Trr) print Trr[key]}' A B | tr ':' ' ' | awk -F'[[:space:]]+' '{print $1,$2,$3,$6}'

위의 설명:

  • IFS그리고오르페우스: 입력 및 출력 파일 구분 기호입니다.
  • [[:space:]]+: 파일 구분 기호에 공백이 여러 개 있으므로 이것을 사용해야 합니다.
  • NR줄 번호처음부터...
  • FNR: 예파일 줄 번호입니다. 여러 파일 이름을 지정하는 awk경우NR그런데 1부터 시작해서FNR파일 변경을 통해 1로 재설정
  • 다음,나머지매우 명확한
  • {}: 통역사의 혼란을 방지하기 위해 모든 블록에서 이것을 사용해야 합니다.

관련 정보