Я предпочитаю обращаться к такого рода вещам, используя инструмент, который может разбивать строку, используя многосимвольный разделитель. Вы можете использовать свой "исключенный шаблон" в качестве разделителя, а затем выполнять замены элементов, которые не являются разделителями. Поскольку мне нравится 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