Як я можу об'єднати файли по черзі?


22

файл кішки1

foo
ice
two

файл кішки2

bar
cream
hundred

Бажаний вихід:

foobar
icecream
twohundred

file1 та file2 завжди матимуть однаковий обсяг рядків у моєму сценарії, якщо це полегшить ситуацію.

Відповіді:


34

Мабуть, правильний інструмент для цієї роботи paste

paste -d '' file1 file2

Детальніше man pasteдив.


Ви також можете скористатися prкомандою:

pr -TmJS"" file1 file2

де

  • -T вимикає пагінацію
  • -mJ м файлів викидів, J повні рядки
  • -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

(Тільки включаючи це, тому що тематика з'явилася в коментарях до іншого запропонованого чистого башти.)


1
Дивовижне, дякую за дуже просте рішення. Чи повинен я коли-небудь турбуватися про портативність, коли мова йде про використання пасти?
TuxForLife

1
@ user264974 паста знаходиться в GNU Coreutils, тому ви, мабуть, досить безпечні.
nettux

8

Через шлях:

awk '{getline x<"file2"; print $0x}' file1
  • getline x<"file2"читає весь рядок з file2 і вміщує в x змінну.
  • print $0xдрукує весь рядок з file1 , використовуючи $0тоді xзбережений рядок file2 .

Дуже добре, що є альтернатива awk, я можу використовувати це замість цього!
TuxForLife

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

Також з чистою 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для читання файлів у масивах, або використовуйте цикл time з двома readкомандами, читаючи з кожного їх fd.
geirha

@geirha Ви маєте рацію, я заплутався з синтаксисом, це нормально зараз.
kos

не зовсім. З оновленим кодом порожні рядки будуть ігноруватися, і якщо будь-який рядок містить глобальні символи, рядок може бути замінено відповідними іменами. Тому ніколи не використовуйте array=( $(cmd) )або array=( $var ). Використовуйте mapfileзамість цього.
geirha

@geirha Ви, звичайно, маєте рацію, я подбав про герої глобальної групи, але я залишив ігнорований новий рядок, тому що для цього і для того, щоб зробити гідне рішення з цього, його потрібно переписати. Я вказав це, і залишу цю версію, якщо вона тим часом стане корисною комусь. Дякуємо за ваші бали досі.
кос

2

Перл-спосіб, легко зрозуміти:

#!/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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.