如何一行一行地合并两个文件

我有两个文件(文件1.txt文件2.txt)。这些文件只是例子。

如何合并这两个文件,以便创建文件 -Merge _ files. txt作为示例3?

我现在正在编写一个 KornShell(ksh)脚本,所以合并可以用 KornShell、 AWKSedPerl一行程序等来完成。

背景-需要合并文件的原因: 我的目标是将 老了文件(存在于第一个字段中)重命名为 新的文件(存在于第二个字段中)。

例子一

文件 文件1.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

文件 文件2.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

文件 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
.
.
.
.
.

示例4(merge _ files.txt 结构)

first field                           second field


OLD file                              NEW file
105852 次浏览

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.

You can use paste to format the files side by side:

$ 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

E.g.:

$ 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

Of course you would want to throw in some safety checks ([ -f "${from}" ], ...).

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

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 EditFile SettingsFile 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

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!
)))