한 파일의 줄을 줄 번호로 다른 파일의 줄로 바꿉니다.

한 파일의 줄을 줄 번호로 다른 파일의 줄로 바꿉니다.

많은 줄이 포함된 fileA.txt가 있고 특정 줄을 여러 줄이 포함된 두 번째 파일 fileB.txt의 다른 특정 줄로 바꾸고 싶습니다.

예: 파일 A.txt

Italy
Korea
USA
England
Peru
Japan
Uruguay

파일B.txt

Argentina
Switzerland
Spain
Greece
Denmark
Singapore
Thailand
Colombia

첫 번째 파일의 2, 4, 5, 7행을 두 번째 파일의 1, 2, 5, 8행으로 바꾸고 싶습니다.

산출:

Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

awk나 sed로 할 수 있을 것 같지만 awk의 경우 이 코드는 두 번째 파일에 대한 줄 정보를 제공하지 않는 것 같습니다.

awk 'NR==FNR{ a[$2]=$1; next }FNR in a{ $0=a[FNR] }1' fileA.txt fileB.txt

어떤 제안이 있으십니까?

답변1

사용 awk:

awk -v a='2,4,5,7' -v b='1,2,5,8' '
BEGIN { split(a, ax, ","); split(b, bx, ",");
        for(n in ax) mapping[ bx[n] ] =ax[n];
};
NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };
{ print (FNR in hold)? hold[FNR]: $0; }' fileB fileA

여기서는 행 번호를 다음과 같이 사용합니다. -va='...'변수가 (파일 A의 경우) 및 b='...'(파일 B의 경우) 에 있으면split()이를 쉼표 문자로 구분된 배열에 넣습니다( a및 은 b변수이고 현재 axbx배열입니다).

mapping그런 다음 ax및 배열에서 또 다른 배열을 만들어 bxfileA의 줄을 fileB의 줄로 바꿔야 합니다.

현재 키(또는 인덱스)mappingarray는 fileB의 줄 번호이고, 이러한 키의 값은 다음과 같이 fileA의 줄 번호입니다.

배열 mapping은 다음과 같습니다

Key    Value
1      2
2      4
5      5
8      7

1이제 우리에게 필요한 것은 위의 키( , 2, 및 5의 FNR ) 와 일치하는 fileB의 줄 번호를 읽는 것입니다. 8따라서 다음을 수행합니다.

NR==FNR { if (FNR in mapping) hold[ mapping[FNR] ]=$0; next; };

좋아요, 지금 가치는 얼마죠 mapping[FNR]? mapping위의 배열을 확인하면 다음과 같습니다.

mapping[1] --> 2; then-we-have    hold[ mapping[1] ] --> hold[2]=$0
mapping[2] --> 4; then-we-have    hold[ mapping[2] ] --> hold[4]=$0
mapping[5] --> 5; then-we-have    hold[ mapping[5] ] --> hold[5]=$0
mapping[8] --> 7; then-we-have    hold[ mapping[8] ] --> hold[7]=$0

따라서 우리는 배열의 값을 mapping배열의 키로 사용합니다. 여기에는 다음이 포함됩니다.holdhold

Key     Value
2       Argentina
4       Switzerland
5       Denmark
7       Colombia

이제 마지막 단계는 배열의 키를 fileA의 일치하는 줄 번호로 사용하는 것입니다 hold. 해당 줄 번호가 배열에 있으면 해당 줄을 배열의 해당 키 값으로 바꾸고, hold찾을 수 없으면 줄을 인쇄합니다. 자체적으로(3개의 메타 연산자: condition? if-true : if-false) 다음과 같이 합니다.

{ print (FNR in hold)? hold[FNR]: $0; }

답변2

사용 표준 sed:

$ printf '%ds/^/%dc\\\\\\\n/p\n' 1 2 2 4 5 5 8 7 | sed -n -f /dev/stdin fileB | sed -f /dev/stdin fileA
Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

명령 파이프라인,

printf '%ds/^/%dc\\\\\\\n/p\n' 1 2 2 4 5 5 8 7 |
sed -n -f /dev/stdin fileB |
sed -f /dev/stdin fileA

먼저 sed각 행 번호 쌍에 대해 대체 명령문을 생성하십시오 printf. 호출의 출력은 printf다음 sed스크립트입니다.

1s/^/2c\\\
/p
2s/^/4c\\\
/p
5s/^/5c\\\
/p
8s/^/7c\\\
/p

이 스크립트는 1, 2, 5, 8행에서 작동하며 sed영향을 받은 행의 시작 부분에 nc\리터럴 개행 문자(특정 행 번호의 경우)를 삽입합니다.n

이 명령을 실행하면 fileB(을 사용하여 sed -n) 새 sed스크립트가 생성됩니다.

2c\
Argentina
4c\
Switzerland
5c\
Denmark
7c\
Colombia

c명령은 한 줄을 다음 텍스트로 바꾸므로 \스크립트는 줄 2, 4, 5, 7을 바꿉니다.

이를 적용하여 fileA결과를 생성합니다.

fileB첫 번째 열에 줄 번호가 포함되고 두 번째 열에 줄 번호가 포함 된 파일에서 줄 번호를 읽습니다 fileA.

$ cat number-pairs
1 2
2 4
5 5
8 7
$ awk '{ printf "%ds/^/%dc\\\\\\\n/p\n", $1, $2 }' number-pairs | sed -n -f /dev/stdin fileB | sed -f /dev/stdin fileA
Italy
Argentina
USA
Switzerland
Denmark
Japan
Colombia

열을 역순으로 저장하려면 표현식에서 및 를 분명히 바꿀 수 있습니다 $1.$2awk

관련 정보