input.txt
,
Linux 시스템에 서로 다른 열( 구분 기호) 을 포함하는 두 개의 파일이 있습니다 . 각 파일의 첫 번째 열에 보고된 ID를 사용하여 이러한 파일을 결합하는 스크립트가 있습니다. 이 스크립트는 출력에서 첫 번째 파일의 모든 ID를 유지하고 두 번째 파일의 일치하는 ID만 유지합니다. 첫 번째 파일의 ID와 일치하지 않는 두 번째 파일의 ID를 유지하는 옵션을 추가하여 이 스크립트를 구현해야 합니다.
예:
2931,C,-9.750,-2.550,57.910,-0.3,C
2932,C,-5.470,-0.200,51.550,0.9,C
2940,C,-10.860,-3.400,54.000,0.7,C
2941,S,-11.820,-13.550,55.070,2.1,S
2944,H,-3.770,-4.180,60.300,0.7,H
2.txt를 입력하세요
4304,N,-9.700,-7.680,58.330,-2.3,N
2940,S,-10.440,-3.450,54.270,2.2,S
2900,C,-13.655,-13.730,59.405,-1.5,C
2931,C,-9.910,-2.420,57.610,0.2,C
주문하다:
join -t, -a1 -o auto <(sort input1.txt) <(sort input2.txt) > output.txt.txt
출력.txt
2931,C,-9.750,-2.550,57.910,-0.3,C,2931,C,-9.910,-2.420,57.610,0.2,C
2932,C,-5.470,-0.200,51.550,0.9,C,,,,,,,
2940,C,-10.860,-3.400,54.000,0.7,C,2940,S,-10.440,-3.450,54.270,2.2,S
2941,S,-11.820,-13.550,55.070,2.1,S,,,,,,,
2944,H,-3.770,-4.180,60.300,0.7,H,,,,,,,
두 개의 출력 파일을 얻기 위해 명령을 수정하고 싶습니다. 첫 번째 항목은 지금 받는 것과 유사해야 하지만 ID도 일치하지 않아야 합니다.
final.txt 출력
2931,C,-9.750,-2.550,57.910,-0.3,C,2931,C,-9.910,-2.420,57.610,0.2,C
2932,C,-5.470,-0.200,51.550,0.9,C,,,,,,,
2940,C,-10.860,-3.400,54.000,0.7,C,2940,S,-10.440,-3.450,54.270,2.2,S
2941,S,-11.820,-13.550,55.070,2.1,S,,,,,,,
2944,H,-3.770,-4.180,60.300,0.7,H,,,,,,,
,,,,,,,2900,C,-13.655,-13.730,59.405,-1.5,C
,,,,,,,4304,N,-9.700,-7.680,58.330,-2.3,N
다른 출력 파일에는 일치하지 않는 다음 줄만 포함되어야 합니다 input2.txt
.
출력2.txt
2900,C,-13.655,-13.730,59.405,-1.5,C
4304,N,-9.700,-7.680,58.330,-2.3,N
또한 input2.txt에서 ID가 4000 이상인 행의 마지막 열 요소만 문자열 "P"로 바꾸려면 어떻게 해야 합니까?
즉, 첫 번째 행(ID = 4304)의 마지막 "C"를 "P"로 바꾸고 싶습니다.
출력.txt
4304,N,-9.700,-7.680,58.330,-2.3,P
2940,S,-10.440,-3.450,54.270,2.2,S
2900,C,-13.655,-13.730,59.405,-1.5,C
2931,C,-9.910,-2.420,57.610,0.2,C
답변1
직업 1:
ID
파일이 고유하다고 가정하면 awk
다음과 같이 사용할 수 있습니다.
awk -F, -v OFS=, '
NR == FNR {
m[$1] = $0
while (i++ <= NF) empty = OFS empty
next
}
!m[$1]{$0 = $0 OFS empty}
m[$1]{$0 = $0 OFS m[$1];delete m[$1]}
1
END{
for ( i in m )
if(m[i]) print empty, m[i]
}
' file2 file1
파일을 정렬할 필요는 없습니다. 공개 필드를 발견할 때마다 배열에서 제거하십시오. 마지막으로 배열은 방금 나타난 콘텐츠만 보유합니다.file2
직업 2:
awk -F, 'NR == FNR {m[$1];next} !($1 in m)' file1 file2
출력 리디렉션을 사용하여 처음 두 내용을 쉘 스크립트에 넣습니다.
#!/bin/bash
# first awk cmd
... > output1.txt
# Second awk cmd
... > output2.txt
답변2
join
모든 필드를 포함하도록 지시하면 원하는 첫 번째 출력 파일을 얻을 수 있습니다. 이 파일은 두 파일의 모든 ID를 포함하는 파일입니다.
$ join -t, -a1 -a2 -o 1.1,1.2,1.2,1.4,1.5,1.6,1.7,2.1,2.2,2.2,2.4,2.5,2.6,2.7 \
<(sort input1.txt) <(sort input2.txt)
,,,,,,,2900,C,C,-13.730,59.405,-1.5,C
2931,C,C,-2.550,57.910,-0.3,C,2931,C,C,-2.420,57.610,0.2,C
2932,C,C,-0.200,51.550,0.9,C,,,,,,,
2940,C,C,-3.400,54.000,0.7,C,2940,S,S,-3.450,54.270,2.2,S
2941,S,S,-13.550,55.070,2.1,S,,,,,,,
2944,H,H,-4.180,60.300,0.7,H,,,,,,,
,,,,,,,4304,N,N,-7.680,58.330,-2.3,N
순서는 파일에서 발견되는 순서이기 때문에 표시된 것과 다릅니다( ,,,,,,,2900...
가 먼저 나타남 sort input2.txt
).
,
그런 다음 첫 번째 출력 파일을 구문 분석하고 하나 이상의 문자로 시작하는 줄을 찾아 두 번째 출력 파일을 얻을 수 있습니다.
$ join -t, -a1 -a2 -o 1.1,1.2,1.2,1.4,1.5,1.6,1.7,2.1,2.2,2.2,2.4,2.5,2.6,2.7 \
<(sort input1.txt) <(sort input2.txt) | grep -oP '^,+\K.*'
2900,C,C,-13.730,59.405,-1.5,C
4304,N,N,-7.680,58.330,-2.3,N
이 옵션은 행에서 일치하는 부분만 인쇄하도록 -o
지시 하고 Perl 호환 정규식을 활성화합니다. 그런 다음 PCRE는 "여기에 일치하는 항목은 모두 무시"라는 의미를 제공하므로 확장된 부분만 인쇄할 수 있습니다 .grep
-P
\K
,
tee
첫 번째 출력을 파일에 쓰고 이를 표준 출력에 쓰는 두 개의 파일을 만드는 단일 명령으로 결합할 수 있으며 , 그런 다음 grep
위와 같이 실행할 수 있습니다.
join -t, -a1 -a2 -o 1.1,1.2,1.2,1.4,1.5,1.6,1.7,2.1,2.2,2.2,2.4,2.5,2.6,2.7 \
<(sort input1.txt) <(sort input2.txt) |
tee output1.txt | grep -oP '^,+\K.*' > output2.txt
최종 출력은 다음과 같습니다.
$ cat output1.txt
,,,,,,,2900,C,C,-13.730,59.405,-1.5,C
2931,C,C,-2.550,57.910,-0.3,C,2931,C,C,-2.420,57.610,0.2,C
2932,C,C,-0.200,51.550,0.9,C,,,,,,,
2940,C,C,-3.400,54.000,0.7,C,2940,S,S,-3.450,54.270,2.2,S
2941,S,S,-13.550,55.070,2.1,S,,,,,,,
2944,H,H,-4.180,60.300,0.7,H,,,,,,,
,,,,,,,4304,N,N,-7.680,58.330,-2.3,N
$ cat output2.txt
2900,C,C,-13.730,59.405,-1.5,C
4304,N,N,-7.680,58.330,-2.3,N