Я предпочитаю обращаться к такого рода вещам, используя инструмент, который может разбивать строку, используя многосимвольный разделитель. Вы можете использовать свой "исключенный шаблон" в качестве разделителя, а затем выполнять замены элементов, которые не являются разделителями. Поскольку мне нравится Perl, я сделаю здесь однострочную версию Perl. :)
Во-первых, потому что "perl" не был одним из предложенных вами решений, я предполагаю, что perl - это не то, в чем вы сильны. Итак, я начну с некоторых вещей, которые вам нужно знать о Perl, чтобы понять, как это работает:
Если вы поместите скобки вокруг шаблона split
функции разделения Perl, разделитель сохраняется как дополнительный элемент в массиве, возвращаемом функцией split
. Используя \[\[.*?\]\]
возвращает нам наименьшую строку, содержащуюся между [[
и ]]
, поэтому в возвращаемом массиве мы можем выбрать элементы, которые не начинаются с [[
и выполнить замену только для этих элементов. При использовании foreach и map $ _ будет ссылкой (указателем) на элемент массива, поэтому изменения в $ _ изменят элементы массива. Таким образом, после изменения массива мы можем просто объединить потенциально измененные элементы и разделители - все еще в правильном порядке - обратно вместе с пустыми символами. Кроме того, мне нравится использовать unless()
то время как другие люди предпочитают, if(!)
( то же самое с моим предпочтениям , используя q{}
, а не ''
потому что ''
выглядит вроде как "
''''
Это не код гольф, и я думаю, что это более читабельно, по-моему. :)
О, и на всякий случай это также ново: perl -lne
the -l
прозрачно обрабатывает переводы строки, которые, я думаю, нам здесь безразличны, но это привычка. -n
помещает код в некоторое while(<>){}
.
С учетом всего вышесказанного, вот рабочий (но бессмысленный) пример, заменяющий все не-ссылки "a" на "pie":
danny@host [/home/danny]
$ cat testfile
a b c d [[a]] b c d [[ moo a moo]] a
I like to eat [[meat]] on a plate
danny@host [/home/danny]
$ perl -nle'@l=split(/(\[\[.*?\]\])/); foreach (@l){s/a/pie/g unless(/^\[\[/)};
print join(q{}, @l)' testfile
pie b c d [[a]] b c d [[ moo a moo]] pie
I like to epiet [[meat]] on pie plpiete