예를 들어 다음과 같은 두 개의 파일이 있습니다.
파일 1:
1
4
X
5
X
7
파일 2:
2
3
5
X
X
1
X
file1의 -lines를 file2의 해당 행 내용으로 바꾸고 싶습니다 .
결과:
1
4
5
5
X
7
나는 같은 CLI 명령을 사용하는 솔루션을 선호합니다 sed
.
답변1
file2가 메모리에 맞으면 awk를 사용할 수 있습니다. 먼저 file2를 읽은 다음 file1을 처리하는 동안 "X"가 표시되면 file2 배열에서 해당 파일을 바꿉니다.
$ awk 'NR == FNR { lines[NR]=$0; } NR != FNR { if ($0 == "X") print lines[FNR]; else print $0 }' file2 file1
다시 포맷하면 다음과 같습니다.
$ awk 'NR == FNR { lines[NR]=$0; }
NR != FNR { if ($0 == "X") print lines[FNR];
else print $0
}' file2 file1
file2는 첫 번째 파일 이름이고 file1은 두 번째 파일 이름입니다.
답변2
$ paste file1 file2 | awk -F '\t' '$1 == "X" { $1 = $2 } { print $1 }'
1
4
5
5
X
7
이 paste
명령은 탭으로 구분된 출력을 생성합니다.
1 2
4 3
X 5
5 X
X X
7 1
첫 번째 필드가 문자인 경우 awk
스크립트는 탭으로 구분된 첫 번째 필드를 두 번째 필드의 콘텐츠로 설정한 X
다음 첫 번째(현재 수정되었을 수 있음) 필드를 인쇄합니다.
다양한 방법글렌 잭맨이 추천하는 작품전달된 데이터를 수정하지 않고 첫 번째 열의 데이터를 기반으로 인쇄할 필드를 선택합니다.
$ paste file1 file2 | awk -F '\t' '{ print $1 == "X" ? $2 : $1 }'
GNU 사용 sed
:
$ paste file1 file2 | sed -E -e '/^X/s/^[^\t]+\t//' -e 's/\t.*$//'
1
4
5
5
X
7
이 두 sed
표현식은 다음을 수행합니다.
- 현재 줄이 로 시작하는 경우
X
첫 번째 교체는 첫 번째 탭을 포함하여 모든 항목을 제거합니다.paste
이렇게 하면 첫 번째 열이 인 경우 출력의 두 번째 열이 첫 번째 열로 효과적으로 이동됩니다X
. - 두 번째 표현식은 탭 문자와 그 뒤에 오는 모든 항목을 제거합니다. 이렇게 하면 관심이 없는 데이터가 제거됩니다.
답변3
배쉬와 함께
while IFS= read -r -u3 f1; IFS= read -r -u4 f2; do
[[ $f1 == X ]] && echo "$f2" || echo "$f1"
done 3<file1 4<file2
또는 더 일반적으로 POSIX
while IFS= read -r f1 <&3; IFS= read -f f2 <&4; do
[ "$f1" = X ] && echo "$f2" || echo "$f1"
done 3<file1 4<file2