developer tip

두 파일을 한 줄씩 일관되게 병합하는 방법

optionbox 2020. 11. 24. 07:56
반응형

두 파일을 한 줄씩 일관되게 병합하는 방법


두 개의 파일 ( file1.txtfile2.txt )이 있으며 파일은 예제 일뿐입니다.

파일을 만들기 위해 두 파일을 병합하는 방법- 예 3과 같이 merge_files.txt

지금 ksh 스크립트를 작성하고 있으므로 ksh, awk, sed, perl one liner ... etc로 병합을 수행 할 수 있습니다.

배경-파일을 병합해야하는 이유 : 내 목표는 OLD 파일 (첫 번째 필드에 있음)을 새 파일 (두 번째 필드에 있음) 로 이름을 바꾸는 것입니다 .

예 1

more file1.txt

/etc/port1-192.9.200.1-255.555.255.0
/etc/port2-192.9.200.1-255.555.255.0
/etc/port3-192.9.200.1-255.555.255.0
/etc/port4-192.9.200.1-255.555.255.0
/etc/port5-192.9.200.1-255.555.255.0
.
.
.
.

예 2

more file2.txt

/etc/port1-192.90.2.1-255.555.0.0
/etc/port2-192.90.2.1-255.555.0.0
/etc/port3-192.90.2.1-255.555.0.0
/etc/port4-192.90.2.1-255.555.0.0
/etc/port5-192.90.2.1-255.555.0.0
.
.
.
.

예 3

 more merge_files.txt



 /etc/port1-192.9.200.1-255.555.255.0  /etc/port1-192.90.2.1-255.555.0.0
 /etc/port2-192.9.200.1-255.555.255.0  /etc/port2-192.90.2.1-255.555.0.0
 /etc/port3-192.9.200.1-255.555.255.0  /etc/port3-192.90.2.1-255.555.0.0
 /etc/port4-192.9.200.1-255.555.255.0  /etc/port4-192.90.2.1-255.555.0.0
 /etc/port5-192.9.200.1-255.555.255.0  /etc/port5-192.90.2.1-255.555.0.0
 .
 .
 .
 .
 .

example4 (merge_files.txt 구조)

 first field                           second field

 OLD file                              NEW file

paste파일을 나란히 포맷하는 데 사용할 수 있습니다 .

$ paste -d" " file1.txt file2.txt
/etc/port1-192.9.200.1-255.555.255.0 /etc/port1-192.90.2.1-255.555.0.0
/etc/port2-192.9.200.1-255.555.255.0 /etc/port2-192.90.2.1-255.555.0.0
/etc/port3-192.9.200.1-255.555.255.0 /etc/port3-192.90.2.1-255.555.0.0
/etc/port4-192.9.200.1-255.555.255.0 /etc/port4-192.90.2.1-255.555.0.0
/etc/port5-192.9.200.1-255.555.255.0 /etc/port5-192.90.2.1-255.555.0.0

예 :

$ paste -d" " file1.txt file2.txt | while read from to; do echo mv "${from}" "${to}"; done
mv /etc/port1-192.9.200.1-255.555.255.0 /etc/port1-192.90.2.1-255.555.0.0
mv /etc/port2-192.9.200.1-255.555.255.0 /etc/port2-192.90.2.1-255.555.0.0
mv /etc/port3-192.9.200.1-255.555.255.0 /etc/port3-192.90.2.1-255.555.0.0
mv /etc/port4-192.9.200.1-255.555.255.0 /etc/port4-192.90.2.1-255.555.0.0
mv /etc/port5-192.9.200.1-255.555.255.0 /etc/port5-192.90.2.1-255.555.0.0

물론 몇 가지 안전 점검을하고 싶을 것입니다 ( [ -f "${from}" ], ...).

Disclaimer: Works only if there are no spaces in your filenames.


This Perl one-liner will display the renames necessary

perl -e 'open $f[$_-1], "file$_.txt" for 1,2; print "rename @n\n" while chomp(@n = map ''.<$_>, @f)'

If this works for you then replace the print statement with a real rename and use

perl -e 'open $f[$_-1], "file$_.txt" for 1,2; rename @n while chomp(@n = map ''.<$_>, @f)'

to do the actual renaming


paste -d " " file1.txt file2.txt

Works great for this job. But in case you are handling text files in a Windows environment and make use of GNU paste, make sure to transform the files to Unix format (CR) and not use files with (CR-LF).

GNU paste does not seem to handle DOS formats properly and parsing is unpredictable, the expected output is erratic and unexpected without warnings.

You may use GVIM to transform them easily (Edit/File Settings/File Format)


Completely unrelated ways to achieve the OP's goal of renaming numbered files:

for f in {1..5}; do mv /etc/port$d-192.9.200.1-255.555.255.0 /etc/port$d-192.90.2.1-255.555.0.0; done

Another possibility based on rename

rename 's/192.9.200.1/192.90.2.1/' /etc/port[1-5]-192.9.200.1-255.555.255.0

command

paste file1 file2

output

/etc/port1-192.9.200.1-255.555.255.0    /etc/port1-192.90.2.1-255.555.0.0
/etc/port2-192.9.200.1-255.555.255.0    /etc/port2-192.90.2.1-255.555.0.0
/etc/port3-192.9.200.1-255.555.255.0    /etc/port3-192.90.2.1-255.555.0.0
/etc/port4-192.9.200.1-255.555.255.0    /etc/port4-192.90.2.1-255.555.0.0
/etc/port5-192.9.200.1-255.555.255.0    /etc/port5-192.90.2.1-255.555.0.0

참고URL : https://stackoverflow.com/questions/16394176/how-to-merge-two-files-consistently-line-by-line

반응형