Вы можете сделать это с помощью rsync
:
rsync -avWxP --exclude Desktop /home/user/ /home/user/Desktop/
Вот один из способов с помощью sed
:
sed '
s|"\(.*\)"[[:blank:]]*:[[:blank:]]*"\(.*\)"|\1\
\2|
h
s|.*\n||
s|[\&/]|\\&|g
x
s|\n.*||
s|[[\.*^$/]|\\&|g
G
s|\(.*\)\n\(.*\)|s/\1/\2/g|
' dictionary.txt | sed -f - novel.txt
Как это работает:
1-й sed
превращает dictionary.txt
в скрипт-файл (команды редактирования, по одной на строку). Он передается во второй sed
(обратите внимание на -f -
, что означает чтение команд из stdin
), который выполняет эти команды, редактируя novel.txt
.
Это требует перевода вашего формата
"STRING" : "REPLACEMENT"
в команду sed
и экранирования любых специальных символов в процессе как для LHS
, так и для RHS
:
s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g
Итак, первая подстановка
s|"\(.*\)"[[:blank:]]*:[[:blank:]]*"\(.*\)"|\1\
\2|
превращает "STRING" : "REPLACEMENT"
в STRING\nREPLACEMENT
(\n
- символ новой строки). Затем результат копируется поверх h
старого пробела.
s|.*\n|||
удаляет первую часть, оставляя только REPLACEMENT
, затем s|[\&/]|\\\\&|g
экранирует зарезервированные символы (это RHS
).
Затем ex
изменяет буфер удержания с пробелом шаблона и s|\n.*||
удаляет вторую часть, оставляя только STRING
и s|[[\.*^$/]|\\\\&|g
выполняет экранирование (это LHS
).
Содержимое буфера удержания затем добавляется в пространство шаблона через G
, так что теперь содержимое пространства шаблона - ESCAPED_STRING\nESCAPED_REPLACEMENT
.
Заключительная подстановка
s|\(.*\)\n\(.*\)|s/\1/\2/g|
преобразует его в s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g
Вот версия на perl. Она создает хэш, содержащий предварительно скомпилированные регулярные выражения, а затем циклически просматривает каждую строку ввода, применяя все регексы к каждой строке. perl
's -i
используется для "редактирования на месте" входного файла. Вы можете легко добавить или изменить любой из регексов или заменяющих строк.
Предварительная компиляция регексов с помощью qr//
значительно повышает скорость работы скрипта, что будет очень заметно при большом количестве регексов и/или большом количестве входных строк для обработки.
#! /usr/bin/perl -i
use strict;
# the dictionary is embedded in the code itself.
# see 2nd version below for how to read dict in
# from a file.
my %regex = (
qr/yes/ => 'no',
qr/stop/ => 'go, go, go!',
qr/wee-ooo/ => 'ooooh nooo!',
qr/gooodbye/ => 'hello',
qr/high/ => 'low',
qr/why\?/ => 'i don\'t know',
);
while (<>) {
foreach my $key (keys %regex) {
s/$key/$regex{$key}/g;
}
}
Вот другая версия, которая считывает словарь из первого имени файла в командной строке, обрабатывая при этом второе (и по желанию последующие) имена файлов:
#! /usr/bin/perl -i
use strict;
# the dictionary is read from a file.
#
# file format is "searchpattern replacestring", with any
# number of whitespace characters (space or tab) separating
# the two fields. You can add comments or comment out dictionary
# entries with a '#' character.
#
# NOTE: if you want to use any regex-special characters as a
# literal in either $searchpattern or $replacestring, you WILL
# need to escape them with `\`. e.g. for a literal '?', use '\?'.
#
# this is very basic and could be improved. a lot.
my %regex = ();
my $dictfile = shift ;
open(DICT,'<',$dictfile) || die "couldn't open $dictfile: $!\n";
while(<DICT>) {
s/#.*// unless (m/\\#/); # remove comments, unless escaped.
# easily fooled if there is an escaped
# '#' and a comment on the same line.
s/^\s*|\s*$//g ; # remove leading & trailing spaces
next if (/^$/) ; # skip empty lines
my($search, $replace) = split;
$regex{qr/$search/} = $replace;
};
close(DICT);
# now read in the input file(s) and modify them.
while (<>) {
foreach my $key (keys %regex) {
s/$key/$regex{$key}/g;
}
}
Начал писать это как комментарий, но получилось слишком сложно, поэтому второй ответ на perl. Учитывая ваш исходный файл, вы можете использовать аккуратный трюк perl для построения regex:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
#build key-value pairs
my %replace = map { /"(.+)"\s*:\s*"(.+)"/ } <DATA>;
print Dumper \%replace;
#take the keys of your hash, then build into capturing regex
my $search = join ( "|", map {quotemeta} keys %replace );
$search = qr/($search)/;
print "Using match regex of: $search\n";
#read stdin or files on command line, line by line
while ( <> ) {
#match regex repeatedly, replace with contents of hash.
s/$search/$replace{$1}/g;
print;
}
__DATA__
"yes" : "no"
"stop" : "go, go, go!"
"wee-ooo" : "ooooh nooo!"
"gooodbye" : "hello"
"high" : "low"
"why?" : "i don't know"
Мы генерируем хэш, используя многострочное совпадение шаблонов и map
для создания пар ключ-значение.
Мы создаем поисковый regex и используем полученные в нем значения для замены.
Использование <>
- магического файлового интерфейса perl - STDIN
или файлов, указанных в командной строке. Примерно так же, как это делает sed. (Вы можете использовать файл и читать его "нормально" для получения шаблона, использование DATA
чисто иллюстративное).