У меня есть длинная строка из поля MySQL, содержащая данные страницы MediaWiki. Я должен заменить строку на этой странице в MediaWiki, но не тогда, когда она находится в ссылке MediaWiki. Ссылка на медиа-вики обозначается двойной квадратной скобкой.

например, заменить "Термин" на «Здесь есть термин, который должен быть заменен», но не заменять «Здесь [[это термин, который]] не должен заменяться»

Решением может быть mysql или sed, awk или что-то еще. Пожалуйста помоги. Спасибо.

3 ответа3

0

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

Просто используйте pywibot's replace.py.

replace.py -exceptinside:link -regex "Term" "New term"

Другие ответы являются неправильными (ненадежными) и излишне сложными.

-1

Вот код, который должен работать для вас. Протестировано на bash в AIX:

#!/usr/bin/bash
#filename: test2.sh
searchandreplace() {
   thisline=$1
   echo $thisline | awk '
BEGIN { FS= "[" }
/\[/ {sub(/Term/,"foobar");print}
!/\[/ {print}
'
}

infile=test.in
cat $infile | while read line
do
   searchandreplace "$line"
done

Вот test.in:

"Here is the Term that has to be replaced" "Here [[is the Term that]] must not be replaced"
third line

Пример при запуске:скриншот, показывающий работу скрипта

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .