Автор Тема: Рег. выражения. Несовсем простая замена слов.  (Прочитано 5397 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн sd1074

  • Завсегдатай
  • Новичок
  • *
  • Сообщений: 40
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Вот возникла такая задача: надо написать регулярное выражение для замены в заданной строке слов: "слово1", "слово2", "слово3" на "слово2", "слово3", "слово4" соответсвенно. В чём хитрость?
Например вариант:

$str=~s/слово1/слово2/g;
$str=~s/слово2/слово3/g;
$str=~s/слово3/слово4/g;

не пододит, т.к. из строки "слово1 слово2 слово3" он сделает "слово3 слово3 слово4", а должен "слово2 слово3 слово4".
То есть нужно сделать как-то, чтобы регулярное выражение, найдя один из образцов, заменило его и повторно уже эта часть строки не подвергалась обработке. Конечно, можно сделать цикл, но хотелось бы как-то написать это одним регулярным выражением. Что-то типа:
$str=~s/слово1|слово2|слово3/слово2|слово3|слово4/g;
Последний вариант синтаксически неверен к сожалению.

Оффлайн arto

  • Ветеран
  • *****
  • Сообщений: 699
  • +0/-0
  • 2
    • Просмотр профиля
Рег. выражения. Несовсем простая замена слов.
« Ответ #1 : 30 Апреля 2007, 16:12:17 »
DB<1> $a = "test word1 word2 word3 test"

  DB<2> $a =~ s|word1 word2 word3|word2 word3 word4|g

  DB<3> p $a
test word2 word3 word4 test

Оффлайн sd1074

  • Завсегдатай
  • Новичок
  • *
  • Сообщений: 40
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Рег. выражения. Несовсем простая замена слов.
« Ответ #2 : 30 Апреля 2007, 16:27:53 »
нене! так не катит. Исходня строка имеет произволный формат.
например, исходнаястрока:
 "Is this word3, or word1? No! This is word2! ";
должна быть преобразована в:
"Is this word4, or word2? No! This is word3! ";

Твой вариант здесь явно не проходит.
В том то и дело же не всё так просто как кажется на первый взгляд. По-моему :)
« Последнее редактирование: 30 Апреля 2007, 16:45:23 от sd1074 »

Оффлайн arto

  • Ветеран
  • *****
  • Сообщений: 699
  • +0/-0
  • 2
    • Просмотр профиля
Рег. выражения. Несовсем простая замена слов.
« Ответ #3 : 30 Апреля 2007, 16:40:27 »
DB<1> $a = "Is this word3, or word1? No! This is word2! "

  DB<2> $a =~ s|word3|word4|g; $a =~ s|word2|word3|g; $a =~ s|word1|word2|g;

  DB<3> p $a
Is this word4, or word2? No! This is word3!

Оффлайн sd1074

  • Завсегдатай
  • Новичок
  • *
  • Сообщений: 40
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Рег. выражения. Несовсем простая замена слов.
« Ответ #4 : 30 Апреля 2007, 17:26:42 »
И это не есть панацея.
В частности мы можем хотеть заменить в тексте слова "word1", "word2" на "word2", "word1" соответсвенно. Или, проще гвооря, поменять их местами.
Но нет необходимости здесь приводить пример позволяющий поменять два слова в тексте местами. Он мне понятен.
Задача стоит более общая. Сейчас попробую чётко сформулировать.

Необходимо разработать программную схему для замены в строке слов: "word1", word2", "word3"... и т.д.  на "wordA", "wordB", "wordC" и т.д. соответсвенно. При этом некоторые написания слов из первой совокупности могут совпадать с какими-то напсианиями слов второй совокупности.

Задача в принципе не сложно решается с использованием цикла, но неужели её нельзя решить с помощью регулярного выражения?!
Для отдельных букв можно было бы использовать транслитерацию tr///g, но мы имеем целые слова.

Оффлайн arto

  • Ветеран
  • *****
  • Сообщений: 699
  • +0/-0
  • 2
    • Просмотр профиля
Рег. выражения. Несовсем простая замена слов.
« Ответ #5 : 30 Апреля 2007, 20:15:46 »
DB<1> $a = "Is this word3, or word1? No! This is word2! "

  DB<2> %hash = (\'word1\' => "word2",\'word2\' => "word3",\'word3\' => "word4")

  DB<3> $re = sprintf "(%s)",join "|",keys %hash

  DB<4> $a =~ s#$re(?!\\000)#$hash{$1}\\000#g

  DB<5> $a =~ s#\\000##g

  DB<6> p $a
Is this word4, or word2? No! This is word3!
  DB<7>

Оффлайн sd1074

  • Завсегдатай
  • Новичок
  • *
  • Сообщений: 40
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Спасибо, хорошее решение. Я сейчас сам поищу, но если вас не затруднит, не могли бы Вы написать пару слов про махинации с \\000. Не совсем понял.

Оффлайн arto

  • Ветеран
  • *****
  • Сообщений: 699
  • +0/-0
  • 2
    • Просмотр профиля
маркируем замененные слова, чтобы их два раза не менять.
во второй раз удаляем маркеры.
\\000 выбран за редкой встречаемостью в строках.

Оффлайн sd1074

  • Завсегдатай
  • Новичок
  • *
  • Сообщений: 40
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ваш метод тем и хорош, что маркеровать не нужно. И ещё я чуток добавил коррекцию на имена первой совокупности.
   my %hash = (
      \'word1\' => "wordA",
      \'word2\'  => "wordB",
      \'word3\'  => "wordC",
   );
   $re = join "|",keys %hash;
   $re=~s/\\\\/\\\\\\\\/g;      #Здесь учтём, что слова первой совокупности могут содержать обратный слэш!
   $txt =~ s/($re)/$hash{$1}/g;
Вроде отлично работает. Спасибо вам.

Оффлайн nal

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 5
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
sd1074
Проверь личные сообщения!
Кое-что отписал тебе.

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28