Как я могу объединить файлы по строкам?

cat file1

foo
ice
two

cat file2

bar
cream
hundred

Желаемый вывод:

foobar
icecream
twohundred

file1 и file2 всегда будут иметь такое же количество в моем сценарии, в случае, если это упростит работу.

1
задан 7 October 2016 в 20:14

4 ответа

Через awk:

awk '{getline x<"file2"; print $0x}' file1
getline x<"file2" читает всю строку из файла2 и удерживается в переменной x. print $0x печатает всю строку из файла1 с помощью $0, затем x, которая является сохраненной строкой файла2.
8
ответ дан 23 May 2018 в 20:51
  • 1
    Очень хорошо иметь альтернативу awk, я могу использовать это вместо этого! – TuxForLife 6 May 2015 в 21:21

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

Обратите внимание, что для неравного числа строк, этот конец будет завершен в последней строке файла, который заканчивается первым.

4
ответ дан 23 May 2018 в 20:51

Кроме того, с чистым 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
3
ответ дан 23 May 2018 в 20:51
  • 1
    Это просто неправильно. Это не работает вообще. Либо используйте mapfile для чтения файлов в массивы, либо используйте цикл while с двумя командами read, считывая с каждого своего fd. – geirha 30 April 2015 в 14:07
  • 2
    @geirha Вы правы, я испортил синтаксис, теперь все в порядке. – kos 30 April 2015 в 14:17
  • 3
    не совсем. С обновленным кодом пустые строки будут игнорироваться, и если какая-либо строка содержит символы glob, строка может быть заменена соответствующими именами файлов. Поэтому никогда не используйте array=( $(cmd) ) или array=( $var ). Вместо этого используйте mapfile. – geirha 30 April 2015 в 15:29
  • 4
    @geirha. Вы правы, конечно, я позаботился о символах glob, но я оставил новую строку проигнорированной, потому что для этого и для того, чтобы сделать из нее достойное решение, ее нужно переписать. Я указал это и оставил эту версию на случай, если кому-то это будет полезно. Спасибо за ваши очки. – kos 30 April 2015 в 17:51

Путь 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
2
ответ дан 23 May 2018 в 20:51

Другие вопросы по тегам:

Похожие вопросы: