75

我有两个文件(file1.txtfile2.txt)。这些文件只是示例。

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

我现在正在编写一个KornShell ( ksh) 脚本,因此可以使用 KornShell、AWKsedPerl单线等来完成合并。

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

示例 1

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

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

文件合并文件.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
4

6 回答 6

129

您可以使用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}" ],...)。

免责声明:仅当文件名中没有空格时才有效。

于 2013-05-06T08:03:36.180 回答
4

这个 Perl 单行代码将显示必要的重命名:

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

如果这对你有用,那么用print真正的重命名替换语句并使用

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

进行实际的重命名。

于 2013-05-06T07:58:25.200 回答
4
paste -d " " file1.txt file2.txt

非常适合这项工作。

但是,如果您在 Windows 环境中处理文本文件并使用 GNU paste,请确保将文件转换为 Unix 格式 (CR) 并且不要使用带有 (CR-LF) 的文件。

GNU paste 似乎不能正确处理 DOS 格式并且解析是不可预测的。预期的输出不稳定且出乎意料,没有警告。

您可以使用gVim轻松转换它们(菜单EditFile SettingsFile Format)。

于 2017-12-21T01:03:34.250 回答
0

实现 OP 重命名编号文件目标的完全不相关的方法:

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

另一种可能性基于rename

rename 's/192.9.200.1/192.90.2.1/' /etc/port[1-5]-192.9.200.1-255.555.255.0
于 2018-01-15T11:22:19.227 回答
0

命令

paste file1 file2

输出

/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
于 2018-01-15T13:50:36.147 回答
0

这是在 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!
)))
于 2020-10-31T05:56:05.347 回答