【问题标题】:How to merge two files consistently line by line如何逐行合并两个文件
【发布时间】:2013-04-29 22:31:45
【问题描述】:

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

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

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

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

示例 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

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

【问题讨论】:

  • 这两个文件的长度总是一样吗? (你最终的目标只是重命名文件,重命名文件后你会删除merge_files.txt?)
  • 不,这只是示例(长度或路径可能更不同),文件内容也可能不同(无需删除 merge_files.txt)

标签: language-agnostic


【解决方案1】:

这个 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)'

进行实际的重命名。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 在 linux 和 solaris 中定义的粘贴命令? ,因为我的脚本将在两个操作系统(linux 和 solaris)上运行
    • paste 可在任何符合POSIX 的系统上使用,并且Linux 和Solaris 都附带它(here 是Oracle 网站上的Solaris 手册页),因此这是一个可移植的解决方案。
    • 如何并排粘贴文件,中间没有空格?即,使用paste -d" " file1.txt file2.txt - 没有空格分隔符? - 提前致谢!
    • @VikasGoel paste -d'\0'(见pubs.opengroup.org/onlinepubs/9699919799/utilities/…)。
    • 有批处理(Windows)等效方法吗?
    【解决方案3】:
    paste -d " " file1.txt file2.txt
    

    非常适合这份工作。

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

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

    您可以使用gVim 轻松转换它们(菜单编辑文件设置文件格式)。

    【讨论】:

    • 有批处理(Windows)等效方法吗?
    【解决方案4】:

    实现 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
    

    【讨论】:

    • 问题是合并文件内容,而不是重命名
    【解决方案5】:

    命令

    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
    

    【讨论】:

      【解决方案6】:

      这是在 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!
      )))
      

      【讨论】:

      • 它不能与缩进一起使用吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 2016-07-30
      • 1970-01-01
      • 2013-10-03
      • 2021-05-11
      • 2020-07-22
      • 2020-09-06
      相关资源
      最近更新 更多