如何逐行合并文件?


22

猫文件1

foo
ice
two

猫文件2

bar
cream
hundred

所需的输出:

foobar
icecream
twohundred

在我的场景中,file1和file2总是具有相同数量的行,以防万一。

Answers:


34

这项工作的正确工具可能是 paste

paste -d '' file1 file2

有关man paste详细信息,请参见。


您还可以使用以下pr命令:

pr -TmJS"" file1 file2

哪里

  • -T 关闭分页
  • -mJ 二哥文件,Ĵ oining实线
  • -S"" 用空字符串分隔列

如果您真的想使用纯bash shell(不建议这样做),那么我建议这样做:

while IFS= read -u3 -r a && IFS= read -u4 -r b; do 
  printf '%s%s\n' "$a" "$b"
done 3<file1 4<file2

(仅包括此内容是因为该主题出现在对另一个提议的纯bash解决方案的评论中。)


1
太好了,谢谢您的非常简单的解决方案。使用粘贴时,我是否应该担心可移植性?
TuxForLife

1
@ user264974粘贴在GNU Coreutils中,因此您可能相当安全。
nettux 2015年

8

通过方式:

awk '{getline x<"file2"; print $0x}' file1
  • getline x<"file2"file2读取整行并保存到x变量中。
  • print $0x通过使用then 打印来自file1的整行,这是file2的保存行。$0x

有一个awk替代方法很好,我可以改用它!
TuxForLife 2015年

4

paste是要走的路。如果要检查其他方法,请使用以下python解决方案:

#!/usr/bin/env python2
import itertools
with open('/path/to/file1') as f1, open('/path/to/file2') as f2:
    lines = itertools.izip_longest(f1, f2)
    for a, b in lines:
        if a and b:
            print a.rstrip() + b.rstrip()
        else:
            if a:
                print a.rstrip()
            else:
                print b.rstrip()

如果行数很少:

#!/usr/bin/env python2
with open('/path/to/file1') as f1, open('/path/to/file2') as f2:
    print '\n'.join((a.rstrip() + b.rstrip() for a, b in zip(f1, f2)))

请注意,对于不相等的行数,此行将在文件的最后一行(最先结束)处结束。


3

另外,使用pure bash(注意,这将完全忽略空行):

#!/bin/bash

IFS=$'\n' GLOBIGNORE='*'
f1=($(< file1))
f2=($(< file2))
i=0
while [ "${f1[${i}]}" ] && [ "${f2[${i}]}" ]
do
    echo "${f1[${i}]}${f2[${i}]}" >> out
    ((i++))
done
while [ "${f1[${i}]}" ]
do
    echo "${f1[${i}]}" >> out
    ((i++))
done
while [ "${f2[${i}]}" ]
do
    echo "${f2[${i}]}" >> out
    ((i++))
done

这是完全错误的。它根本不起作用。使用mapfile将文件读取到数组中,或者使用带有两个read命令的while循环,从每个命令读取它们的fd。
geirha 2015年

@geirha你是对的,我搞砸了语法,现在可以了。
kos 2015年

不完全的。使用更新的代码,空行将被忽略,并且如果任何行包含glob字符,则该行可能会替换为匹配的文件名。因此,请勿使用array=( $(cmd) )array=( $var )。使用mapfile代替。
geirha 2015年

@geirha您当然是对的,我已经照顾了glob字符,但是我忽略了换行符,因为要这样做并为了得到一个不错的解决方案,需要重写它。我指定了此版本,并在此版本离开时以免对某人有用。到目前为止,感谢您的观点。
kos 2015年

2

Perl方式,简单易懂:

#!/usr/bin/perl
$filename1=$ARGV[0];
$filename2=$ARGV[1];

open(my $fh1, "<", $filename1) or die "cannot open < $filename1: $!";
open(my $fh2, "<", $filename2) or die "cannot open < $filename2: $!";

my @array1;
my @array2;

while (my $line = <$fh1>) {
  chomp $line;
  push @array1, $line;
}
while (my $line = <$fh2>) {
  chomp $line;
  push @array2, $line;
}

for my $i (0 .. $#array1) {
  print @array1[$i].@array2[$i]."\n";
}

从...开始:

./merge file1 file2

输出:

foobar
icecream
twohundred
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.