LINUX.ORG.RU

Матчинг содержимого кавычек

 ,


0

1

Вроде бы простая задача, но у меня не получается сделать лучше, чем «в лоб»:

foreach (qq("abcedefhjhj")) { 
 /^(?<quo>['"])(?<text>(??{ '[^'.$+{quo}.']+' }))\g{quo}$/ && 
   print "match found\n" 
}

Есть 2 требования к регэксу:

1) Кавычки могут быть одинарными или двойными, мы заранее не знаем, какие именно будут использованы;

2) Внутри текста, заключенного в кавычки, не должны содержаться эти самые кавычки.

КАК правильно-то??

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 2)

Ответ на: комментарий от disarmer

И оно захавает всё подряд между одними кавычками и другими, включая, как ни странно, кавычки. А ещё Perl обязательно намекнёт, что \1 - сильно deprecated.

Насчёт матчинга именованными группами - не обращайте внимания, это сделано просто для наглядности. Суть проблемы в использовании этого самого (??{})

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от DRVTiny

Ну ограничь жадность квантификатором "?":

% perl -wE 'use strict;qq("abcedefhjhj")=~m/(["])(.+?)(\1)/ and say $2'
abcedefhjhj

Когда это \1 отменили? v5.20.1, никто ни на что не намекает. Ты видимо имеешь ввиду про «\1 better written as $1 at -e line 1.», но это только если указывать в качестве замены в s///

disarmer ★★★
()
Ответ на: комментарий от disarmer

Ага, а теперь всё то же самое (с нежадным разбором), но с описанием всей строки, то есть со включенными якорями ^ и $

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Ничего не понял, при чём тут якоря, вся строка должна быть в кавычках? Тогда можно добавить якоря в регексп

m/^(["])(.+?)\1$/

Если надо все строки найти, то лучше так:

% perl -wE '$_=qq("first"test"second");while(s/(["])(.+?)\1//){say $2}'
first
second

disarmer ★★★
()

2) Внутри текста, заключенного в кавычки, не должны содержаться эти самые кавычки.

даже экранированные?

Deleted
()
while (m#([''"])(\\\1|.)*?\1#gs) { print $& }
arto ★★
()
Ответ на: комментарий от disarmer
perl -wE '$a=qq("Lebed, rak and "Roga and kopyta"); say scalar($a=~m/^(["])(.+?)\1$/?"":"not ")."matched"'

Что-то тут не то, Вы не находите? Есть некий «подвох» в этом нежадном разборе :)

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от disarmer

Экранированные тем более одним нежадным разбором не накроешь. А вот методика с «запоминанием» группировки и динамическим формированием регэкспа как раз очень кстати здесь была бы.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

А вот методика с «запоминанием» группировки и динамическим формированием регэкспа как раз очень кстати здесь была бы.

facepalm

Есть 2 требования к регэксу:

1) Кавычки могут быть одинарными или двойными, мы заранее не знаем, какие именно будут использованы;

2) Внутри текста, заключенного в кавычки, не должны содержаться эти самые кавычки.

КАК правильно-то??

/"[^"]*"|'[^']*'/
Deleted
()
Ответ на: комментарий от Deleted

Та ну, гениально просто, офигеть можно, сразу видно нуба!

А если выражение для внутреннего содержимого кавычек чутка посложнее, чем просто «лишь бы не обрамляющая кавычка», а если, как тут уже говорили, хочется иметь возможность экранировать кавычки, а если, в конце концов, видов кавычек чуть больше, чем два?

А ещё таки да, извлечение группирвовок из альтернативного выбора - весьма своеобразная задача. То есть извлекаются конечно, но их нумерация весьма неочевидна, а если, не дай Бог, в разных частях альтернативного выбора разное количество групп - то это и вовсе полный вынос мозга.

Ну и да, дорогой товарищ, где ж якоря начала и конца строки?! Что, кривож*пие у всех в крови что ли?

С якорями-то ваш альтернативный выбор ещё и в скобки придётся впедрячить.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Собственно, вопрос-то был не о том, как в целом составить это выражение, я итак знаю, что мой вариант - правильный (слабо доказать обратное?). Вопрос был в том, почему, собственно, в конструкции [^SOMETHING] этот самый SOMETHING не может быть ссылкой на прежде сделанную группировку. Такое впечатление, что класс символов - такой же некомпилируемый keyword-константа (только в рамках данного конкретного регэкспа), как и, например, скобки или не к ночи помянутый символ «|».

В общем, если кто-нибудь ответит, почему, собственно, я не могу сделать:

(abcde)[^\1]

- буду крайне признателен.

Также принимаются варианты с использованием «отрицательного предпросмотра».

Нубские «упрощения» не интересуют ни разу, уж извините.

DRVTiny ★★★★★
() автор топика
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от DRVTiny

Не знаю, если есть нужда в таких сложных регулярках, то возможно быстрее будет накидать нормальную грамматику? Её, как минимум, будет проще поддерживать.

anonymous
()
Ответ на: комментарий от DRVTiny

Что просили, то и дадено. Если вам надо что-то другое, учитесь формулировать свои мысли.

а если, как тут уже говорили, хочется иметь возможность экранировать кавычки

Делается за 30 секунд, точно так же как и без. Оставлю вам в качестве домашнего задания. Справочник по регулярным выражениям нагуглите самостоятельно. Но сначала не помешает почитать, что такое вообще регулярные выражения, и какие грамматики ими парсятся.

а если
и еще таки да
и т.д. и т.п.
бла-бла-бла

сразу видно нуба!

Ага, сразу видно нуба-ТСа, не способного даже грамотно поставить вопрос.

Deleted
()
Ответ на: комментарий от DRVTiny

Вопрос был в том, почему, собственно, в конструкции [^SOMETHING] этот самый SOMETHING не может быть ссылкой на прежде сделанную группировку. Такое впечатление, что класс символов - такой же некомпилируемый keyword-константа (только в рамках данного конкретного регэкспа), как и, например, скобки или не к ночи помянутый символ «|».

Потому что ты, нуб, пытаешься натянут регулярные выражения на КС-грамматику, и удивляешься, что оно не налазит. Брысь читать википедию, раз в универе основам не научили.

Deleted
()

Правда говорят, что перл приводит к разжижению мозга.

Чувак придумал себе КЗ-грамматику (сначала написал КС-грамматику, потом подумал... понял, что у ТСа размах даже шире, мелко не берёт), пытается её парсить регуляркой и удивляется, почему регулярками она не парсится.

В общем, если кто-нибудь ответит, почему, собственно, я не могу сделать: (abcde)[^\1] - буду крайне признателен.

Потому что молотком надо забивать гвозди, а лопатой - копать. «В общем, если кто-нибудь ответит, почему, собственно, я не могу копать молотком - буду крайне признателен.» Ага, ага. И в самом деле, почему?

5 звёзд, итить. Лядский стыд.

Deleted
()
Ответ на: комментарий от anonymous

Чего ты такой агрессивный?

А интересна мне реакция ТСа. Сам-то он удалой молодец выводить рулады а ля «Та ну, гениально просто, офигеть можно, сразу видно нуба!» Посмотрим, что будет, если его чутка макнуть в овно.

Deleted
()
Ответ на: комментарий от Deleted

5 звёзд, итить. Лядский стыд.

Я вот думаю, что и меня когда-нибудь пять звезд будет. И что тогда, ничего не писать, я должен стать непогрешимым от этих звездочек?)

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Я вот думаю, что и меня когда-нибудь пять звезд будет. И что тогда, ничего не писать, я должен стать непогрешимым от этих звездочек?)

Ну если у тебя будет 5 звёзд, а ты к тому времени не научишься грамотно задавать вопросы, как не научился это делать ТС, то что ж поделать... будут анонимусы стебать тебя. :P

Deleted
()
Ответ на: комментарий от Deleted

Потому что ты, нуб, пытаешься натянут регулярные выражения на КС-грамматику

Документацию Perl'а читать не пробовал? Грамматика регулярных выразжений Perl действительно запросто может быть нерегулярной. Например, запросто реализуется матчинг рекурсивно вложенных скобок.

Насчёт контекстной свободности - да, не учил таких умных слов, у меня другая инженерная специальность. Тем не менее я регулярные выражения средней сложности могу составлять под практически любые свои нужды. Насчёт Вас я в этом плане сомневаюсь: знаний регулярных выражений для утилиты egrep при программировании на Perl - крайне мало.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Делается за 30 секунд, точно так же как и без

А ты слился. Что ж, бывает.

Ступай обратно grep'ить в консольке.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Оно вообще JSON парсит, это высший пилотаж, мне ещё 250 лет нужно, чтобы достигнуть столь мощного просветления.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от anonymous

но зачем так жить.

Диагноз подтвердился: ТС - перлоилита с разжиженным мозгом, которой в детстве показали регулярки, и с тех пор он уверовал.

Deleted
()
Ответ на: комментарий от DRVTiny

матчинг строк с экранированными кавычками

> Делается за 30 секунд, точно так же как и без

А ты слился. Что ж, бывает.

мне ещё 250 лет нужно, чтобы достигнуть столь мощного просветления.

Воистину, чтобы придумать регулярку

([^"\\]|\\"|\\\\)
, нужно МОЩНОЕ ПРОСВЕТЛЕНИЕ.

Иди уроки учи, дзен-буддист ты наш.

Deleted
()
Ответ на: комментарий от DRVTiny

Насчёт контекстной свободности - да, не учил таких умных слов,

Вот потому, что ты не знаешь нихрена об используемом инструменте, и веруешь в Суперправильный Код На Регулярках Который Может Делать Всё.

Например, запросто реализуется матчинг рекурсивно вложенных скобок.

Реализуется, потому что перловики всю жизнь были с прибабахом, и раширили обычный автомат регулярок до кривого и сложного КС-автомата, имеющего входной язык в стиле брейнфак. Спрашивается: зачем так жить, если можно взять НОРМАЛЬНЫЙ КС-автомат? А ответ прост: потому что для этого о существовании такого автомата надо ЗНАТЬ. А вы не знаете нихрена, «инженеры» доморощенные.

Не спорю, к молотку можно присобачить саперную лопатку. ВОт только считать, что КОПАТЬ такое лопатой — это высший пилотаж, это лол. А ля «папуасу показали зажигалку».

у меня другая инженерная специальность.

Пустобрех — это не инженерная, а гуманитарная специальность.

Deleted
()
Ответ на: комментарий от DRVTiny

http://www.perlmonks.org/?node_id=995856

Открываем и... о боже, что же мы видим?! Ту самую регурялку для экранированных строк, которую невозможно написать за 30 секунд. :D

(?<STRING>
  (
    "
    (?:
      [^\\"]+
    |
      \\ ["\\/bfnrt]
#    |
#      \\ u [0-9a-fA-f]{4}
    )*
    "
  )

  (?{ [$^R, eval $^N] })
)

мне ещё 250 лет нужно

Ты верно уловил суть своего невежества!

Deleted
()
Ответ на: комментарий от DRVTiny

Продолжаем ликбез. Твоё «почему, собственно, я не могу сделать: (abcde)[^\1]» не может быть распознано ни регуляркой, ни КС-автоматом.

Почему? Потому что для КС-автомата любой терминал или нетерминал X равен любому другому терминалу или нетерминалу X. Если у тебя в грамматике написано «на X начинается, потом бла-бла-бла, на X заканчивается», то у тебя нет никакого способа сообщить, что второй X должен быть в каком-то смысле «такой же как первый». Потому что у автомата нет памяти для пройденных терминалов/нетерминалов, и он их никак не запоминает. Именно поэтому он и называется, контекстно-свободным, дубинушка!

Но вы, неучи, рассчитываете, что при помощи автомата регулярных выражений, вам дадут парсить регулярные грамматики, КС-грамматики, КЗ-грамматики, китайский язык, астрал, и бонусом — возможность призывать сатану. Вот с призывом сатаны при таком подходе как раз всё ОК, а писать содержательный код — как-то не получается. На выходе, как обычно, кривой и глючный брейнфак, который реализует 80% задачи в полнолуние в четверг. Ведь «нубские знания» ВУЗовского курса вас «не интересуют ни разу», ага.

Он встал за машинку и шикарным жестом перекинул тумблер. В недрах машинки загорелась неоновая лампочка.

— Прошу вас, — повторил старичок.

— А что это у вас там за лампа? — подозрительно спросил Фарфуркис.

Старичок ударил по клавишам, потом быстро вырвал из машинки листок бумаги и рысцой поднес его Фарфуркису. Фарфуркис прочитал вслух:

— «Вопрос: что у нея… гм… у нея внутре за лпч?..» Лэпэчэ… Кэпэдэ, наверное? Что еще за лэпэчэ?

— Лампочка, значит, — сказал старичок, хихикая и потирая руки. — Кодируем помаленьку. — Он вырвал у Фарфуркиса листок и побежал обратно к своей машинке. — Это, значит, был вопрос, — произнес он, загоняя листок под валик. — А сейчас посмотрим, что она ответит…

Члены Тройки с интересом следили за его действиями. Профессор Выбегалло благодушно-отечески сиял, изысканными и плавными движениями пальцев выбирая из бороды какой-то мусор. Эдик пребывал в спокойной, теперь уже полностью осознанной тоске. Между тем старичок бодро постучал по клавишам и снова выдернул листок.

— Вот, извольте, ответ.

Фарфуркис прочитал:

— «У мене внутре… гм… не… неонка». Гм. Что это такое — неонка?

— Айн секунд! — воскликнул изобретатель, выхватил листок и вновь подбежал к машинке. Дело пошло.

То-то и оно.

Deleted
()

Как-то так:

#!/usr/bin/perl

$str = qq{"test" '"hehe"' \"wow\" \'"\"imposible"\'};
$start = 0;
$end = 0;
$quotes = qq{"|'|\"|\'};
$look = qr/$quotes/;

$\ = "\n";

while ($str =~ /($look)/g) {
  if ( $start == 0 ) {
    $start = pos($str);
    $look = qr/$1/;
    next;
  }

  if ( $end == 0 ) {
    $end = pos($str);
    print substr($str, $start, $end - $start - 1);
    $start = $end = 0;
    $look = qr/$quotes/;
  }
}
А вообще я бы использовал index (perldoc -f index), т.к. это в 100 раз надежней и быстрее регепсов, ну почти в 100 раз :-)

gh0stwizard ★★★★★
()
Ответ на: комментарий от Deleted

Реализуется, потому что перловики всю жизнь были с прибабахом, и раширили обычный автомат регулярок до кривого и сложного КС-автомата

Если из Ж. руки растут и не умеешь читать документацию по используемому тобой инструменту, то в общем только ботаном-аспирантом и работать за миску невкусной баланды.

Любому программисту на Perl глубоко плевать, какая грамматика у регэкспов - лишь бы задачу решала. В данном случае мой регэксп задачу решает, а твой - тоже вроде решает, но шаг в сторону - и придётся в каждую ветку альтернативного выбора вписывать одно и то же. Либо писать отдельный код для разбора грамматики. Ну что, если делать нечего, и это никому не мешает, то почему бы и нет.

И да, если код с регэкспами выполняется слишком медленно - ему ищутся альтернативы. Но не потому что грамматика не та, а потому что критериям приемлемого быстродействия не соответствует.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от Deleted

а писать содержательный код — как-то не получается.

Задача всегда - написать код, который работает и работа этого когда соответствует конкретным условиям, определяемым тем или иным заказчиком.

Писать «содержательный код», критерии содержательности которого, очевидно, определяет тот, у кого МПХ длиннее или должность толще, - это как бы не цель разработки ПО. Целью является результат деятельности - готовая программа.

Иначе это какой-то онанизм, процесс ради процесса.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Воистину, чтобы придумать регулярку

Вот этот кусок Г?

([^"\\]|\\"|\\\\)

А, собственно, какую задачу-то она решает? Матчит «не кавычку», «экранированную кавычку» или «два бэкслэша».

Слушай, а ты не забыл о том, что сам символ кавычки должен определяться динамически? Вообще в этом вопрос-то был, а не в том, умеешь ты составлять примитивные регэкспы или нет.

Да, и это... в Perl-regexp'ах вообще-то не принято группировать тупо скобками то, что не нужно «запоминать» для последующего использования. Хотя да, в твоём идеалистически-ботаническом мирке «автомат» ничего не запоминает!

DRVTiny ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.