IMHO.WS

IMHO.WS (http://www.imho.ws/index.php)
-   Программирование (http://www.imho.ws/forumdisplay.php?f=40)
-   -   И снова регулярные выражения (http://www.imho.ws/showthread.php?t=94152)

Hubbitus 13.10.2005 16:25

И снова регулярные выражения
 
Уважаемые, спасибо за Ваше внимание вообще.

Задача в общем виде:

Нужно сопоставить шаблону ЛИБО одно слово (разделение пробелом) ЛИБО все выражение в кавычках (пусть в одинарных, не суть)

Чтобы все однозначно всеми понималось, пару примеров:
1) Есть текст $text = '123456 qaz qwerty';
Хочу чтобы выбралось 123456
2) Есть текст $text = "'123456 qaz' qwerty";
Хочу чтобы выбралось 123456 qaz - Без кавычек

Итак, в чем основная сложность и до чего я пока додумался:
1)
PHP код:

preg_match_all("#\'(.*?)\'|(\d+)#i"$text$matchesPREG_SET_ORDER); 

2)
PHP код:

preg_match_all("#(\'.*?\'|\d+)#i"$text$matchesPREG_SET_ORDER); 

Вот, впринципе, обе решают какбы поставленную задачу, но оба варианта не доконца/не так как бы хотелось:
В первом случае номера совпадений для выражения в кавычках и для одиночного слова будут разными, порядковыми (1 и 2 соответственно), это и понятно - ведь 2 раза захватывается паттерн, два раза круглые скобки, но хочется чтобы было в одном элементе.
Во втором случае элемент 1, НО, захватываются еще и сами кавычки, а хотелось бы без них (чтобы потом не анализировать это). Как их исключить там - пока не додумался.

Буду благодарен свежим мыслям и конкретным решениям.

crawler 22.06.2006 18:26

Подниму тему.
Возможно ли найти строку НЕ содержащюю подстроку ? Что-то вида
Код:

.*!(ТЕХТ).*
чтобы в результате поиска на отсутвие "пять":
Код:

1. Раз два три
2. четыре пять
3. шесть семь

нашла 1 и 3 строку.

Нужно это поставить в linefilter WinMerge (там стоит автоматический NOT), для поиска измененных строк содержащих определенное слово.

Gr@nd@d 23.06.2006 06:52

Цитата:

Сообщение от crawler
Возможно ли найти строку НЕ содержащюю подстроку ?

Imho чисто самим выражением в общем случае нельзя.
Попробуй поиграться с модификатором "?!", например: (?!ТвойТекст), только без всяких там ".*" - эти схавают что угодно ;)

EvroStandart 26.06.2006 12:49

А по моему очень даже можно.
Крыша ^ не в самом начале означает отрицание. Получается примерно так:
{(^пять)}
Как вариант можно искать своё слово и потом проверять было ли совпадение: {пять}
:)

Gr@nd@d 27.06.2006 14:09

Цитата:

Сообщение от EvroStandart
А по моему очень даже можно. Как вариант можно искать своё слово и потом проверять было ли совпадение: {пять}

Так у него, насколько я понял, выражение вставляется в какой-то парсер и доп.проверку туда не вставить. А "крышка" дает отрицание в квадратных скобках "[^...]", а не в круглых. Это называется инвертированный символьный класс. По крайней мере по стандарту.

EvroStandart 27.06.2006 16:51

ага, я фигурные скобки с квадратными перепутал. А круглые - это группировка, внитри них всё также должно работать. Но тут они наверно вообще ничего не маняют :)

Gr@nd@d 28.06.2006 13:51

Цитата:

Сообщение от EvroStandart
А круглые - это группировка, внитри них всё также должно работать.

По стандарту - увы, не должно. В утилитах (greep например) для инверсии маски обычно ключ специальный предусмотрен, типа "найти все, что НЕ совпадает с указанной маской".

Цитата:

Сообщение от Gr@nd@d
Попробуй поиграться с модификатором "?!"

Я не знаю, какая реализация регулярных выражений используется, но для очистки совести еще попробовал бы вариант: "(ТвойТекст){0,0}".
У меня под линухом не сработал, но чем черт не шутит? ;)

crawler 28.06.2006 18:51

Совесть чиста ;( .Судя по всему поиска на отсутсвие стринга не предусмотрено, так как видел предложение добавить такую опцию в "feature requests"

В круглых скобках знак ^ не имеет значения "not", только в квадратных.

is_absent 11.07.2006 15:14

^([^a][^b][^c])*$

LAndrew2 15.11.2006 00:22

подскажие, плз, каким регулярным выражением можно "зацепить" и удалить следующие строчки
Код:

<DIV><A href="text.html" class="more">... whole issue</A></DIV>
<DIV><A href="article.html" class="more">... все статьи </A></DIV>
<DIV><A href="channel.html" class="more">... другие материалы</A></DIV>

если что, язык Jscript (хотя это не так важно)

делаю так
Код:

var reg = /<A href=\"[0-9a-zA-Z_\.]+\" class=\"more\">[0-9a-zA-Z_а-яА-Я\.]+<\/A>/
text = text.replace(reg, "");

но вроде где-то ошибка...

Hubbitus 15.11.2006 04:17

LAndrew2 на первый взгляд все верно, только пробелы не учтены, возможно что-то вроде:
Код:

var reg = /<A href=\"[0-9a-zA-Z_\.]+\" class=\"more\">.+?<\/A>/g
text = text.replace(reg, "");

подойдет

LAndrew2 15.11.2006 12:18

вроде работает... а что означает конструкция
Код:

.+?
?

а! вроде понял... любое кол-во символов (за исключением символа новой строки) и любое (в т.ч. нулевое) кол-во слов...

Hubbitus 15.11.2006 15:49

Цитата:

LAndrew2:
а что означает конструкция
.+?
От одного и более символов, наименьшей длины, чтобы удовлетворить шаблону. Входит ли символ новой строки туда или нет зависит от модификаторов, по умолчанию не входит, да.

LAndrew2 17.01.2007 12:08

есть задача:
1) имеется список имен файлов, все имена в определенном формате,
данный формат задается пользователем, например, "%l4 - %l1 - %l2.mp3", где, например, %l1 исполнитель, %l2 - композиция, %l4 - трек
2) имеется набор файлов, все имена этих файлов также в определенном формате, заданном пользователем, например, "track %f4 %f#.mp3", где, например, %f1 исполнитель, %f2 - композиция, %f4 - трек, %f# - любые символы
3) задано, например, что файл в списке соответствует реальному файлу, если %l4=%f4 (это условие может меняться пользователем)
необходимо смэтить реальные файлы с файлами в списке и показать "реальное имя -> имя в списке" для каждого файла

для выполнения задачи необходимо использование регулярных выражений, для поиска соответствий необходимо заменить все выражения типа %l или %f на (.*), но чтобы потом получить и использовать значения (порядок которых может быть произвольным), надо как-то запоминать в какой позиции (.*) оказалось.
потому вопрос: возможно ли значениям в скобках, типа (.*), присваивать имена и потом к ним обращаться по именам, а не по номеру в массиве?

is_absent 17.01.2007 12:14

(?P<name>expression) если я не ошибаюсь

LAndrew2 17.01.2007 16:14

что-то такая конструкция
(?P<name>.*)
не срабатывает на VBScript :(
есть еще варианты?

is_absent 17.01.2007 16:55

на http://www.regular-expressions.info/vbscript.html написано, что на VBScript изя делать так... меняй язык :)

LAndrew2 18.01.2007 09:34

is_absent,
на что? :))
а как можно сделать в VBScript? может какая-то другая конструкция есть?

Hubbitus 18.01.2007 16:52

А на Java-Script тоже не работает? (это так, просто предложение попробовать, проверять нету времени)

is_absent 18.01.2007 16:57

Цитата:

Сообщение от LAndrew2 (Сообщение 1338259)
а как можно сделать в VBScript? может какая-то другая конструкция есть?

Я не силен в этом :) можно попробовать руками организовать эту функцию. т.е. сначала выполняем обычное регулярное выражение, а следующим шагом формируем массив с именами (т.е. нужно будет соответствие индекс скобки -- имя).


Цитата:

Сообщение от Hubbitus (Сообщение 1338643)
А на Java-Script тоже не работает?

судя по-всему тоже не работает...

StasK 31.01.2007 02:08

Можно ли как то искать шаблон до определенной строки ?
Например, есть строка:

PHP код:

/( [0-9]+:[0-9]+)   $/ 

ее нужно искать пока не встретиться строка:

PHP код:

---- ---- ---- ... и т.д


EvroStandart 31.01.2007 12:52

По моему, там нет такой логики
Цитата:

Сообщение от StasK (Сообщение 1346341)
пока не встретиться строка

Регулярное выражение ищет всё подряд.

Hubbitus 31.01.2007 20:04

StasK, почему нет:
PHP код:

/( [0-9]+:[0-9]+)   $.*?---- ---- ----/ms 


StasK 02.02.2007 00:06

а между ???

PHP код:

---- ---- ---- ... и т.д.
кусок для поиска
---- ---- ---- ... и т.д


Hubbitus 02.02.2007 15:48

Ну и между:
PHP код:

/---- ---- ----(.*?( [0-9]+:[0-9]+)   $.*?)+---- ---- ----/ms 


crawler 02.02.2007 23:31

Это работает только если есть единственное появление "кусок для поиска" внутри "блока". А найти второе появление искомого текста внутри такого "блока" практически никак

StasK 03.02.2007 01:36

как раз и нужно искать столько "кусков для поиска" сколько встретиться.

Hubbitus 03.02.2007 12:25

Цитата:

Сообщение от StasK (Сообщение 1348480)
как раз и нужно искать столько "кусков для поиска" сколько встретиться.

Да, так последний будет захвачен. Я думаю в подобной задаче, лучше текст на куски разбить другими средствами, тем же explode и не мчаться.

StasK 03.03.2007 22:05

Еще одно выражение
 
Еще одно выражение:

PHP код:

/$.*?===[0-9].*?===$  $  $/[

или что бы понятнее:

/$                             
// символ прогона страницы
.*?===[0-9].*?===$     // любые символы, затем ===, какое-то число и снова ===
  
$                             // два пробела
  
$/                            // два пробела 

Задача: вырезать каждую последовательность этих строк.
НО: не работает, а если оставить какую-нибудь одну строку, то пожалуйста :(

Как это победить ?

crawler 11.03.2007 14:19

Собсно кто вам сказал что '$' - это прогон страницы ? Попробуй заменить на "\n"

Hubbitus 12.03.2007 08:49

Цитата:

Сообщение от StasK (Сообщение 1367838)
НО: не работает, а если оставить какую-нибудь одну строку, то пожалуйста

А модификаторы multiline стоят??

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

StasK 13.03.2007 22:15

Цитата:

Сообщение от Hubbitus
Приведите конкретнее пример - пример текста

PHP код:

*    (символ прогона страницы не отображается здесь)
.............................................===
2===
..  
.. 

Поясню:
1-я строка - символ прогона страницы
2-я строка - куча пробелов, затем ===(тут какое-то число)===
3-я строка - два пробела
4-я строка - два пробела

до и после этого куска идет список: Номер пункта и наименование
таких "кусков" около 1500 шт. (и убирать их ручками долговато)

Цитата:

Сообщение от Hubbitus
пример работы с ним

пробовал так ($ - вроде как конец строки):
PHP код:

/$.*?===[0-9].*?===$  $  $/ 

Цитата:

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

язык: АWК
результат: пусто
оставляю какое-нибудь одно условие: работает

Melkor 14.03.2007 00:23

Ой, а мне можно тоже спросить, если у вас такая тема интересная. Уже замучался.
"Куча слов (\S+\.?\S*|\.\S+) \[\d+\]";
Прекрасно ловит фразу:

"Куча слов слово [5]" (без кавычек)

Но не видит фразу:
"Куча слов еще слово [5]"

Как сделать так, чтобы между "Куча слов " и "[5]" ловилось все, там может стоять фраза любой длины (ну порядка 20 символов) из латиницы и цифр.
Спасибо.

Добавил:
'@(Куча слов )?([^/[]+)@'
дает в [2]м результате нужное, но только если перед фразой ничего не стоит.

crawler 14.03.2007 12:20

Melkor,
Цитата:

Но не видит фразу: "Куча слов еще слово [5]"
(\S+\.?\S*|\.\S+)
- тут же нет пробелов, вот 2 слова и не ловятся, только одно

примерно так ?
"Куча слов ([ \w]+) \[\d+\]"
А если ты хотел 2 слова, то \S+\s+\S+

StasK, "$" - это окончание строки. На одной строке может быть только 1 КОНЕЦ и уж никак не 4. Тем более что ты хочешь работать с многостроковым текстом.
"символ прогона страницы" это символ FormFeed ASCII code 12?
Цитата:

оставляю какое-нибудь одно условие: работает
ясно что на 1 строку и работает.
попробуй
/\n.*?===[0-9].*?===\n \n \n/

StasK 14.03.2007 20:14

Цитата:

Сообщение от crawler (Сообщение 1373589)
"$" - это окончание строки. На одной строке может быть только 1 КОНЕЦ и уж никак не 4.

понятно

Цитата:

Сообщение от crawler (Сообщение 1373589)
"символ прогона страницы" это символ FormFeed ASCII code 12?

да

Цитата:

Сообщение от crawler (Сообщение 1373589)
попробуй
/\n.*?===[0-9].*?===\n \n \n/

результат - пусто

crawler 15.03.2007 11:59

FormFeed ASCII code 12 обозначается "\f"
awk вообще-то работает построчно. чтобы его заставить работать с несколькими строками нужно менять RS и FS

StasK 15.03.2007 20:34

Цитата:

Сообщение от crawler (Сообщение 1374274)
FormFeed ASCII code 12 обозначается "\f"

понятно

Цитата:

Сообщение от crawler (Сообщение 1374274)
awk вообще-то работает построчно. чтобы его заставить работать с несколькими строками нужно менять RS и FS

как это сделать?

crawler 16.03.2007 15:55

http://www.gnu.org/software/gawk/man...iple-Line.html
http://www.skywayradio.com/tech/awk/index.html

Hubbitus 20.03.2007 00:20

Вложений: 1
Цитата:

Сообщение от StasK (Сообщение 1374652)
как это сделать?

Приблизительно вот так:
Код:

BEGIN {
RS="\f +===[0-9]===\n  \n  \n"
}

{ print $0 }

Ну и исходя из приведенного Вами примера, пробовал на таком вот файле (единственное, символа \f ставить не стал). Работающий пример на gawk в аттаче.

StasK 21.03.2007 21:05

Цитата:

Сообщение от Hubbitus (Сообщение 1377307)
Приблизительно вот так:

спасибо!!!

а теперь: как вырезать это все ???
т.е. что бы текст, который был после этого, стал сразу за текстом который был перед блоком без пустых строк ?
такое возможно?


Часовой пояс GMT +4, время: 20:28.

Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.