Чтобы расширить ответ @RoVo, вы можете использовать цикл for для повторения всех ваших запросов:
for term in "kwd1" "kwd2" "kwd3" "kwd4" "kwd5"; do
grep "$term" search_file.txt || echo "string"`
done
Вы можете использовать для этого paste
, просто установите разделитель на новую строку:
$ paste -d'\n' file1 file2 file3
A
E
I
B
F
J
C
G
K
D
H
L
#!/usr/bin/perl
use strict;
# how many files to open? 10 in the question, 3 in examples.
my $numfh=3;
# a counter for the number of open file handles
my $openfh=$numfh;
# open an array of filehandles, one for each input file.
my @fh = ();
for my $i (1..$numfh) {
open($fh[$i],"<","file$i.txt") || die "Couldn't open file$i.txt for read: $!";
};
# open the output file.
open (my $out,">","bigfile.txt") || die "Couldn't open bigfile.txt for write: $!";
# repeat until there are no more open file handles.
until ($openfh < 1) {
for my $i (1..$numfh) {
if (eof($fh[$i])) {
# if an input file is eof, close it and decrement openfh counter.
$openfh--;
close($fh[$i]);
} else {
# print a line of input from the current input file to the output file.
print $out scalar readline $fh[$i]
};
};
}
Сохраните это как, например, merge.pl
и сделайте его исполняемым с помощью chmod +x merge.pl
. Затем запустите его вот так:
$./merge.pl
Выход:
$ cat bigfile.txt
A
E
I
B
F
J
C
G
K
D
H
L
а вот версия с использованием @ARGV и выводом в STDOUT для @terdon:
#!/usr/bin/perl
use strict;
my @fh = ();
my $i=1;
for my $f (@ARGV) {
open($fh[$i++], "<", $f) || die "Couldn't open $f for read: $!";
};
my $numfh=$#fh; my $openfh=$numfh;
until ($openfh < 1) {
for my $i (1..$numfh) {
if (eof($fh[$i])) {
$openfh--;
close($fh[$i]);
} else {
print scalar readline $fh[$i]
};
};
}
Или использовать хеш для хранения дескрипторов файлов вместо массива:
#!/usr/bin/perl
use strict;
my %fh = ();
for (@ARGV) {
open($fh{$_}, "<", $_) || die "Couldn't open $_ for read: $!";
};
while (keys %fh) {
for my $f (@ARGV) {
next unless (defined($fh{$f}));
if (eof($fh{$f})) {
close($fh{$f});
delete($fh{$f});
} else {
print scalar readline $fh{$f}
};
};
}
Запустите как:
$./merge.pl file[123].txt > bigfile.txt
Вывод идентичен жестко закодированной -версии.
Вот альтернатива paste
(, протестированная с GNU pr
и оболочкой, поддерживающей ANSI -C, цитирующая)
pr -mts$'\n' <files>
Одним из преимуществ является то, что опция -s
будет работать и для многосимвольного разделителя.
Поскольку sed
помечен, вы можете использовать R
команду (, доступную на GNU sed
, не уверен в других реализациях ).
sed -e 'R f2' -e 'R f3' f1
Используя GNU sed , мы можем использовать команду R
read для постепенного извлечения верхних строк из входных файлов для получения объединенного вывода.
sed -e "
$(printf 'R%s\n' file{2..9}.txt file10.txt)
" file1.txt
perl -lne '
push @{$A[@ARGV]}, $_}{
for my $i (0..$#{$A[0]}){
print for map { $A[$_][$i] } reverse 0..$#A
}
' file{1..9}.txt file10.txt
Здесь мы храним файлы в AoA, также известном как двумерный массив @A. Первый индекс относится к позиции файла в списке позиционных аргументов, а второй индекс относится к данным этого конкретного файла. В конечном блоке }{
мы сжимаем массив, выбирая один элемент из каждого массива.