'How to merge two files consistently line by line
I have two files (file1.txt & file2.txt ). The files are only examples.
How can I merge the two files, in order to create the file - merge_files.txt as example 3?
I am now writing a KornShell (ksh) script, so merge can be done with KornShell, AWK, sed, a Perl one-liner, etc.
Background - why I need to merge the files: my target is to rename the old file (exist in first field) to a new file (exist in the second field).
Example 1
File 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
.
.
.
.
Example 2
File 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
.
.
.
.
Example 3
File 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
.
.
.
.
.
Example 4 (merge_files.txt structure)
first field second field
OLD file NEW file
Solution 1:[1]
This Perl one-liner will display the necessary renames:
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.
Solution 2:[2]
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 do 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 (menu Edit ? File Settings ? File Format).
Solution 3:[3]
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
Solution 4:[4]
Here's sample code to merge files in Windows CMD:
: Count number of lines to merge
for /f "tokens=*" %i in ('find /c /v "" ^< test2.txt') do set /a n=%i<nul
: Read 2 files & merge line by line
for /l %a in (1,1,%n%) do (
for /f "tokens=*" %i in ('find /v /n "" ^< test1.txt ^| find "[%a]"') do (
for /f "tokens=*" %j in ('find /v /n "" ^< test2.txt ^| find "[%a]"') do (
set a=%i
set b=%j
set a=!a:*]=!
set b=!b:*]=!
echo:!a! -- !b!
)))
Solution 5:[5]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Peter Mortensen |
| Solution 2 | Peter Mortensen |
| Solution 3 | Peter Mortensen |
| Solution 4 | Peter Mortensen |
| Solution 5 | Peter Mortensen |
