많은 줄이 포함된 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
여기서는 행 번호를 다음과 같이 사용합니다.앗 -v
a='...'
변수가 (파일 A의 경우) 및 b='...'
(파일 B의 경우) 에 있으면split()
이를 쉼표 문자로 구분된 배열에 넣습니다( a
및 은 b
변수이고 현재 ax
는 bx
배열입니다).
mapping
그런 다음 ax
및 배열에서 또 다른 배열을 만들어 bx
fileA의 줄을 fileB의 줄로 바꿔야 합니다.
현재 키(또는 인덱스)mapping
array는 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
배열의 키로 사용합니다. 여기에는 다음이 포함됩니다.hold
hold
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
.$2
awk