awk
не может этого сделать (без использования какого-либо цикла), но perl
может.
Однако помните, что массивы perl
отсчитываются от нуля (в то время как индексы массивов awk
начинаются с 1).
Например, при использовании параметра -a
в perl
для awk
-подобного автоматического разделения:
$ echo p1 p2 p3 p4 p5 p6 p7 | perl -ane 'print "@F[3..$#F]\n";'
p4 p5 p6 p7
$ echo p1 p2 p3 p4 p5 p6 p7 | perl -ane 'print "@F[2,4,6]\n";'
p3 p5 p7
$ echo p1 p2 p3 p4 p5 p6 p7 | perl -ane 'print "@F[1..3]\n";'
p2 p3 p4
см. man perldata
или perldoc perlvar
для получения дополнительной информации о массивах и срезах массивов.
Поскольку фрагменты массива печатаются внутри строки, заключенной в двойные кавычки, для разделения элементов массива используется значение $ "
, также известное как $ LIST_SEPARATOR
. Если они были напечатаны / используется вне строки, заключенной в двойные кавычки, между элементами вообще не будет разделителя. См. man perlvar
или perldoc perlvar
и поиск LIST_SEPARATOR.
Наконец, не надо t используйте perl -a
, если ваш разделитель полей не является пробелом ( \ s +
в PCRE).Разбейте его самостоятельно следующим образом:
$ echo "p1:p2:p3:p4:p5:p6:p7" | perl -n -e '@F=split /:/; print "@F[0..4]\n";'
p1 p2 p3 p4 p5
Перл спешит на помощь!
Считайте пары замен в хэш. Затем прочитайте ввод построчно и попробуйте заменить совпадения.
#!/usr/bin/perl
use warnings;
use strict;
open my $ot, '<', 'old-text.txt' or die $!;
chomp( my @lines = <$ot> );
open my $nt, '<', 'new-text.txt' or die $!;
my %replace;
@replace{@lines} = <$nt>;
chomp for values %replace;
my $regex = join '|', map quotemeta, @lines;
open my $in, 'naive-file.txt' or die $!;
while (<$in>) {
s/($regex)/$replace{$1}/;
print;
}
Если некоторые из заменяемых строк являются подстроками других заменяемых строк, необходимо отсортировать строки в регулярном выражении по убыванию их длины, т.е.
my $regex = join '|', map quotemeta, sort { length $b <=> length $a } @lines;
Вот GNU awk
один -вкладыш:
awk 'NR==FNR{old[++k]=$0}FILENAME=="new-text.txt"{new[FNR]=$0}
FILENAME=="naive-file.txt"{for(i=1;i<k;i++)if(old[i]==$0)$0=new[i];print}'\
old-text.txt new-text.txt naive-file.txt
Может не подходить для очень больших файлов, так как все шаблоны сначала сохраняются в массивах.
Выход:
Sed id ligula quis est convallis tempor.
This is the new text.
It could also have multiple lines and special characters like these \ { & %
etc...
Nunc aliquet, augue nec adipiscing interdum, lacus tellus malesuada massa, quis
varius mi purus non odio.
Баш
Заменить первое совпадение:
target=$(cat naive-file.txt)
old=$(cat old-text.txt)
new=$(cat new-text.txt)
echo "${target/"$old"/"$new"}"
Заменить все совпадения:
echo "${target//"$old"/"$new"}"
Заменить начальное совпадение:
echo "${target/#"$old"/"$new"}"
Заменить конец совпадения:
echo "${target/%"$old"/"$new"}"
$ perl -0777ne '
$A[@ARGV] = $_;
@ARGV and next;
my($naive, $new, $old) = @A;
while ( index($naive,$old,$p) > -1 ) {
substr($naive, index($naive,$old,$p), length($old)) = $new;
$p = index($naive,$old,length($old)) ;
}
print $naive;
' old.txt new.txt naive.txt