Как найти кавычку регулярном выражении

I’m looking for a way to search a text file for quotes made by author and then print them out. My script so far:

import re

    #searches end of string 
    print re.search('"$', 'i am searching for quotes"')

    #searches start of string 
    print re.search('^"' , '"i am searching for quotes"')

What I would like to do

import re

## load text file
quotelist = open('A.txt','r').read()

## search for strings contained with quotation marks
re.search ("-", quotelist)

## Store in list or Dict
Dict = quotelist

## Print quotes 
print Dict

I also tried

import re

buffer = open('bbc.txt','r').read()

quotes = re.findall(r'.*"[^"].*".*', buffer)
for quote in quotes:
  print quote

# Add quotes to list

 l = []
    for quote in quotes:
    print quote
    l.append(quote)

MERose's user avatar

MERose

3,9087 gold badges53 silver badges77 bronze badges

asked May 8, 2012 at 15:46

aromamode's user avatar

1

Develop a regular expression that matches all the expected characters you would expect to see inside of a quoted string. Then use the python method findall in re to find all occurrences of the match.

import re

buffer = open('file.txt','r').read()

quotes = re.findall(r'"[^"]*"',buffer)
for quote in quotes:
  print quote

Searching between ” and ” requires a unicode-regex search such as:

quotes = re.findall(ur'"[^u201d]*u201d',buffer)

And for a document that uses ” and ” interchangeably for quotation termination

quotes = re.findall(ur'"[^"^u201d]*["u201d]', buffer)

answered May 8, 2012 at 15:58

lukecampbell's user avatar

lukecampbelllukecampbell

14.7k4 gold badges34 silver badges32 bronze badges

9

You don’t need regular expressions to find static strings. You should use this Python idiom for finding strings:

>>> haystack = 'this is the string to search!'
>>> needle = '!'
>>> if needle in haystack:
       print 'Found', needle

Creating a list is easy enough –

>>> matches = []

Storing matches is easy too…

>>> matches.append('add this string to matches')

This should be enough to get you started. Good luck!

An addendum to address the comment below…

l = []
for quote in matches:
    print quote
    l.append(quote)

answered May 8, 2012 at 15:56

jaime's user avatar

jaimejaime

2,2061 gold badge18 silver badges22 bronze badges

6

Шпаргалка по регулярным выражениям

Квантификаторы

  Аналог Пример Описание
? {0,1} a? одно или ноль вхождений «а»
+ {1,} a+ одно или более вхождений «а»
* {0,} a* ноль или более вхождений «а»

Модификаторы

Символ «минус» (-) меред модификатором (за исключением U) создаёт его отрицание.

  Описание
g глобальный поиск (обрабатываются все совпадения с шаблоном поиска)
i игнорировать регистр
m многострочный поиск. Поясню: по умолчанию текст это одна строка, с модификатором есть отдельные строки, а значит ^– начало строки в тексте, $– конец строки в тексте.
s текст воспринимается как одна строка, спец символ «точка» (.) будет вкючать и перевод строки
u используется кодировка UTF-8
U инвертировать жадность
x игнорировать все неэкранированные пробельные и перечисленные в классе символы

Спецсимволы

  Аналог Описание
()   подмаска, вложенное выражение
[]   групповой символ
{a,b}   количество вхождений от «a» до «b»
|   логическое «или», в случае с односимвольными альтернативами используйте []
  экранирование спец символа
.   любой сивол, кроме перевода строки
d [0-9] десятичная цифра
D [^d] любой символ, кроме десятичной цифры
f   конец (разрыв) страницы
n   перевод строки
pL   буква в кодировке UTF-8 при использовании модификатора u
r   возврат каретки
s [ tvrnf] пробельный символ
S [^s] любой символ, кроме промельного
t   табуляция
w [0-9a-z_] любая цифра, буква или знак подчеркивания
W [^w] любой символ, кроме цифры, буквы или знака подчеркивания
v   вертикальная табуляция

Спецсимволы внутри символьного класса

  Пример Описание
^ [^da] отрицание, любой символ кроме «d» или «a»
[a-z] интервал, любой симво от «a» до «z»

Позиция внутри строки

  Пример Соответствие Описание
^ ^a aaa aaa начало строки
$ a$ aaa aaa конец строки
A Aa aaa aaa
aaa aaa
начало текста
z az aaa aaa
aaa aaa
конец текста
b ab
ba
aaa aaa
aaa aaa
граница слова, утверждение: предыдущий символ словесный, а следующий – нет, либо наоборот
B BaB aaa aaa отсутствие границы слова
G Ga aaa aaa Предыдущий успешный поиск, поиск остановился на 4-й позиции — там, где не нашлось a

Скачать в PDF, PNG.

Якоря

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

^[0-9]+

Здесь символ ^обозначает начало строки. Без него шаблон соответствовал бы любой строке, содержащей цифру.

Символьные классы

Символьные классы в регулярных выражениях соответствуют сразу некоторому набору символов. Например, dсоответствует любой цифре от 0 до 9 включительно, wсоответствует буквам и цифрам, а
W— всем символам, кроме букв и цифр. Шаблон, идентифицирующий буквы, цифры и пробел, выглядит
так:

ws

POSIX

POSIX — это относительно новое дополнение семейства регулярных выражений. Идея, как и в случае с символьными
классами, заключается в использовании сокращений, представляющих некоторую группу символов.

Утверждения

Поначалу практически у всех возникают трудности с пониманием утверждений, однако познакомившись с ними ближе, вы
будете использовать их довольно часто. Утверждения предоставляют способ сказать: «я хочу найти в этом документе
каждое слово, включающее букву “q”, за которой не следует “werty”».

[^s]*q(?!werty)[^s]*

Приведенный выше код начинается с поиска любых символов, кроме пробела ([^s]*), за которыми следует
q. Затем парсер достигает «смотрящего вперед» утверждения. Это автоматически делает предшествующий
элемент (символ, группу или символьный класс) условным — он будет соответствовать шаблону, только если
утверждение верно. В нашем случае, утверждение является отрицательным (?!), т. е. оно будет верным,
если то, что в нем ищется, не будет найдено.

Итак, парсер проверяет несколько следующих символов по предложенному шаблону (werty). Если они найдены,
то утверждение ложно, а значит символ qбудет «проигнорирован», т. е. не будет соответствовать шаблону.
Если же wertyне найдено, то утверждение верно, и с qвсе в порядке. Затем продолжается
поиск любых символов, кроме пробела ([^s]*).

Кванторы

Кванторы позволяют определить часть шаблона, которая должна повторяться несколько раз подряд. Например, если вы
хотите выяснить, содержит ли документ строку из от 10 до 20 (включительно) букв «a», то можно использовать этот
шаблон:

a{10,20}

По умолчанию кванторы — «жадные». Поэтому квантор +, означающий «один или больше раз», будет
соответствовать максимально возможному значению. Иногда это вызывает проблемы, и тогда вы можете сказать квантору
перестать быть жадным (стать «ленивым»), используя специальный модификатор. Посмотрите на этот код:

".*"

Этот шаблон соответствует тексту, заключенному в двойные кавычки. Однако, ваша исходная строка может быть вроде
этой:

<a href="helloworld.htm" title="Привет, Мир">Привет, Мир</a>

Приведенный выше шаблон найдет в этой строке вот такую подстроку:

"helloworld.htm" title="Привет, Мир"

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

".*?"

Этот шаблон также соответствует любым символам, заключенным в двойные кавычки. Но ленивая версия (обратите внимание
на модификатор ?) ищет наименьшее из возможных вхождений, и поэтому найдет каждую подстроку в двойных
кавычках по отдельности:

"helloworld.htm" "Привет, Мир"

Экранирование в регулярных выражениях

Регулярные выражения используют некоторые символы для обозначения различных частей шаблона. Однако, возникает
проблема, если вам нужно найти один из таких символов в строке, как обычный символ. Точка, к примеру, в регулярном
выражении обозначает «любой символ, кроме переноса строки». Если вам нужно найти точку в строке, вы не можете просто
использовать «.» в качестве шаблона — это приведет к нахождению практически всего. Итак, вам
необходимо сообщить парсеру, что эта точка должна считаться обычной точкой, а не «любым символом». Это делается с
помощью знака экранирования.

Знак экранирования, предшествующий символу вроде точки, заставляет парсер игнорировать его функцию и считать обычным
символом. Есть несколько символов, требующих такого экранирования в большинстве шаблонов и языков. Вы можете найти
их в правом нижнем углу шпаргалки («Мета-символы»).

Шаблон для нахождения точки таков:

.

Другие специальные символы в регулярных выражениях соответствуют необычным элементам в тексте. Переносы строки и
табуляции, к примеру, могут быть набраны с клавиатуры, но вероятно собьют с толку языки программирования. Знак
экранирования используется здесь для того, чтобы сообщить парсеру о необходимости считать следующий символ
специальным, а не обычной буквой или цифрой.

Спецсимволы экранирования в регулярных выражениях

Выражение Соответствие
не соответствует ничему, только экранирует следующий за ним символ. Это нужно, если вы хотите ввести метасимволы !$()*+.<>?[]^{|}в качестве их буквальных значений.
Q не соответствует ничему, только экранирует все символы вплоть до E
E не соответствует ничему, только прекращает экранирование, начатое Q

Подстановка строк

Подстановка строк подробно описана в следующем параграфе «Группы и диапазоны», однако здесь следует упомянуть о
существовании «пассивных» групп. Это группы, игнорируемые при подстановке, что очень полезно, если вы хотите
использовать в шаблоне условие «или», но не хотите, чтобы эта группа принимала участие в подстановке.

Группы и диапазоны

Группы и диапазоны очень-очень полезны. Вероятно, проще будет начать с диапазонов. Они позволяют указать набор
подходящих символов. Например, чтобы проверить, содержит ли строка шестнадцатеричные цифры (от 0 до 9 и от A до F),
следует использовать такой диапазон:

[A-Fa-f0-9]

Чтобы проверить обратное, используйте отрицательный диапазон, который в нашем случае подходит под любой символ, кроме
цифр от 0 до 9 и букв от A до F:

[^A-Fa-f0-9]

Группы наиболее часто применяются, когда в шаблоне необходимо условие «или»; когда нужно сослаться на часть шаблона
из другой его части; а также при подстановке строк.

Использовать «или» очень просто: следующий шаблон ищет «ab» или «bc»:

(ab|bc)

Если в регулярном выражении необходимо сослаться на какую-то из предшествующих групп, следует использовать
n, где вместо nподставить номер нужной группы. Вам может понадобиться шаблон,
соответствующий буквам «aaa» или «bbb», за которыми следует число, а затем те же три буквы. Такой шаблон реализуется
с помощью групп:

(aaa|bbb)[0-9]+1

Первая часть шаблона ищет «aaa» или «bbb», объединяя найденные буквы в группу. За этим следует поиск одной или более
цифр ([0-9]+), и наконец 1. Последняя часть шаблона ссылается на первую группу и ищет то
же самое. Она ищет совпадение с текстом, уже найденным первой частью шаблона, а не соответствующее ему. Таким
образом, «aaa123bbb» не будет удовлетворять вышеприведенному шаблону, так как 1будет искать «aaa»
после числа.

Одним из наиболее полезных инструментов в регулярных выражениях является подстановка строк. При замене текста можно
сослаться на найденную группу, используя $n. Скажем, вы хотите выделить в тексте все слова «wish»
жирным начертанием. Для этого вам следует использовать функцию замены по регулярному выражению, которая может
выглядеть так:

replace(pattern, replacement, subject)

Первым параметром будет примерно такой шаблон (возможно вам понадобятся несколько дополнительных символов для этой
конкретной функции):

([^A-Za-z0-9])(wish)([^A-Za-z0-9])

Он найдет любые вхождения слова «wish» вместе с предыдущим и следующим символами, если только это не буквы или цифры.
Тогда ваша подстановка может быть такой:

$1<b>$2</b>$3

Ею будет заменена вся найденная по шаблону строка. Мы начинаем замену с первого найденного символа (который не буква
и не цифра), отмечая его $1. Без этого мы бы просто удалили этот символ из текста. То же касается конца
подстановки ($3). В середину мы добавили HTML тег для жирного начертания (разумеется, вместо него вы
можете использовать CSS или <strong>), выделив им вторую группу, найденную по шаблону
($2).

Модификаторы шаблонов

Модификаторы шаблонов используются в нескольких языках, в частности, в Perl. Они позволяют изменить работу парсера.
Например, модификатор iзаставляет парсер игнорировать регистры.

Регулярные выражения в Perl обрамляются одним и тем же символом в начале и в конце. Это может быть любой символ (чаще
используется «/»), и выглядит все таким образом:

/pattern/

Модификаторы добавляются в конец этой строки, вот так:

/pattern/i

Мета-символы

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

(

Шпаргалка представляет собой общее руководство по шаблонам регулярных выражений без учета специфики какого-либо языка.
Она представлена в виде таблицы, помещающейся на одном печатном листе формата A4.
Создана под лицензией Creative Commons на базе шпаргалки, автором которой является Dave Child.
Скачать в PDF, PNG.

  1. Регулярные выражения

Цитата
Сообщение от Vovan-VE
Посмотреть сообщение

ruzab, Если экранирование есть вообще, то и проверять его надо с самого начала. Не забывайте про такие ситуации:

PHP
1
echo "foo \"; // ";

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

Я понял. Думаю для меня это не страшно, поскольку я не собираюсь делать из строки переменные. Я пытаюсь сделать в шаблоне, который беру из БД возможность писать условие

PHP
1
if(условие1){результат1} elseif(условие2){результат2} ... else {результат N}

Но мне не нужно чтобы ошибку выдавал сам eval, а я хочу смастерить микро анализатор кода (т.е. условия if elseif .. else), чтоб понять, правильно ли составлен запрос с точки зрения синтаксиса php и самостоятельно прервать выполнение кода в случае нахождения ошибки.
А чтобы соответственно проверить правильно-ли эти условия в скобках составлены, мне необходимо проанализировать пунктуацию того, что там (в скобках):
это строка: “строка” или так: ‘строка’ (как раз без неэкранированных кавычек, а другие символы там в принципе имеют право быть в т.ч. экранированная кавычка, например: ‘стро’ка’.)
integer: 10,
float: 10.5,
выражение: 10 == 10, ‘x’ != ‘y’ и т.п. .
false
true
null

Конечно это не полнофункциональный код php: там можно писать минимум условий и результат внутри {…} может быть только строкой.

Цитата
Сообщение от Vovan-VE
Посмотреть сообщение

Опасная затея. Если Вам это нужно для подстановки переменных, то зря Вы это задумали. Чтобы сделать PHP-инъекцию, не обязательно закрывать кавычку и писать после ; следующий оператор:

PHP
1
2
3
4
# PHP 5.3+
echo "foo {$x[$f=function(){ echo 'lol'; }][$f()]} bar";
# PHP 5.0 - 5.2
echo "foo {$x[$f=create_function('','echo 'lol';')][$f()]} bar";

См. также Тонкости сложных переменных в строках

Спасибо. Это мощно. Возьму на заметку

Попробовал ваш пример:

PHP
1
2
3
if (preg_match('/^([^\\"]|\\.)*/', $str, $m)) {
    echo $m[0];
}

он заработал (правда я его под свои задачи подкорректировал), но мне только непонятно, зачем в данном шаблоне ставить столько бэкслешей :По большому счету, как я понимаю, если в шаблоне ставится один бэкслеш, то он экранирует что-то, квадратную скобку например.
‘/^([^]])*/’

А если ставится 2 обратных слэша, то он экранирует сам себя, т.е. обозначает некий одинокий бэкслеш, стоящий гдето в строке, Но почемуто [^\] не работает, а работает [^\\”]… Я бы это прочитал как 2 бэкслеша стоящие гдето подряд в строке …

Я чегото совсем с этими бэкслешами запутался…

Давайте рассмотрим два эффективных способа, которые касаются экранированных кавычек. Эти шаблоны не предназначены для краткости и эстетики, но для эффективности.

Эти способы используют первое распознавание символов для быстрого поиска котировок в строке без затрат на чередование. (Идея состоит в том, чтобы быстро отбросить символы, которые не являются кавычками, без проверки двух ветвей чередования.)

Контент между кавычками описывается с помощью развернутого цикла (вместо повторного чередования), чтобы быть более эффективным: [^"\]*(?:\.[^"\]*)*

Очевидно, что для обработки строк, которые не имеют сбалансированных кавычек, вместо этого вы можете использовать притяжательные кванторы: [^"\]*+(?:\.[^"\]*)*+ или обходной путь для имитации их, чтобы предотвратить слишком много возврата. Вы также можете выбрать, что цитируемая часть может быть открывающей цитатой до следующей (неэкспертированной) цитаты или конца строки. В этом случае нет необходимости использовать притяжательные квантификаторы, вам нужно только сделать последнее предложение необязательным.

Обратите внимание: иногда кавычки не сбрасываются с помощью обратного слэша, но повторяя цитату. В этом случае подшаблон содержимого выглядит так: [^"]*(?:""[^"]*)*

Шаблоны избегают использования группы захвата и обратной ссылки (я имею в виду что-то вроде (["']).....1) и используют простое чередование, но с ["'] в начале, в коэффициенте.

Perl вроде:

["'](?:(?<=")[^"\]*(?s:\.[^"\]*)*"|(?<=')[^'\]*(?s:\.[^'\]*)*')

(обратите внимание, что (?s:...) является синтаксическим сахаром для включения режима dotall/singleline внутри группы, не содержащей захвата. Если этот синтаксис не поддерживается, вы можете легко включить этот режим для всего шаблона или заменить точку на [sS])

(Способ написания этого шаблона полностью “ручным” и не учитывает возможные внутренние оптимизации двигателя)

ECMA script:

(?=["'])(?:"[^"\]*(?:\[sS][^"\]*)*"|'[^'\]*(?:\[sS][^'\]*)*')

POSIX расширен:

"[^"\]*(\(.|n)[^"\]*)*"|'[^'\]*(\(.|n)[^'\]*)*'

или просто:

"([^"\]|\.|\n)*"|'([^'\]|\.|\n)*'

Регулярные выражения для чайников

В большинстве своем 80% современного программирования сведены к анализу и работе с информацией. А информация всегда предоставляется нам в текстовой форме, просто потому, что другие ее формы анализу так легко не поддаются. Проще говоря одна из первых задач, с которой сталкивается любой программист, это парсинг информации. А где парсинг, там и регулярные выражения. О них мы сегодня и поговорим ибо выяснилось, что многие понятия не имеют, что это такое, и с чем это едят. После прочтения этой статьи вы поймете как создавать свои регулярные выражения, а так-же как с ними работать. Ниже даже пример на php есть.

О регулярных выражениях

И так, что же такое регулярное выражение?

/<as*href='(.+?)'/

Я, таки, могу прямо сюда скопировать описание из википедии, но думаю лучше просто показать, ибо объяснить как оно работает на словах очень сложно. Тут надо понять. Причем самому. Но определение я все-таки дам:

Регулярное выражение — это маска, по которой можно искать определенные данные в тексте или искать и заменять эти самые данные.

Что позволяют делать эти «магические конструкции» и почему так важно уметь их использовать? На самом деле все просто.
Предположим, нам надо найти все теги <div> в строке. Пишем регулярное выражение, скармливаем ему строчку и все!

preg_match("/<div[^>]*>(.+?)</div>/is",$data,$matches);

Начинающий кодер, таки, может спросить: но разве то-же самое нельзя сделать через strpos и substr? Да, это можно сделать, но давайте просто сравним количество кода:

$spos=stripos($html,"<div");
$lpos=$spos=stripos($html,"</div");
if($spos !== false && $lpos !== false)
$result = substr($spos,$spos-$lpos);

Как вы видите, регулярные выражения экономят кучу времени. Да, для новичка они выглядят как нечто ужасное, сродни ктулху. Однако, страшного там ничего нет и сегодня вы в этом убедитесь.

Учимся понимать регулярные выражения

Прежде чем что-то писать или объяснять, я бы хотел представить вам инструмент для работы с регулярками, это RegExr. Откройте его в новой вкладке и прорабатывайте там все примеры, которые я буду приводить.
Начнем с простого, с чего начинал я сам. С получения содержимого атрибута тега. Предположим нам надо взять атрибут href="ссылка" из тега ссылки. Как нам это сделать?
Давайте откроем ide RegExr и в нижнем поле впишем html код ссылки.

Теперь собственно составим регулярку. Что мы знаем?
1. Атрибут начинается с href и содержит знак равно, с двумя кавычками по краям.
2. Нужные нам данные находятся между этих кавычек и эти данные могут меняться случайный образом

Пункт 1 решается крайне просто. Давайте укажем в верхнем поле известные нам данные:

Теперь собственно обратимся к пункту номер 2.

Как указать строку, которая меняется случайным образом? Чтобы понять строку, надо понять из чего она состоит. (с) Любая случайная строка состоит из случайных букв и(или) символов, которые указаны в ней в различном (любом) порядке. Чтож, откроем справочник регулярных выражений. Лучший из встреченных мной, это справочник от microsoft. Не смотрите, что там указано, якобы справочник для javascript. В большинстве своем регулярные выражения работают одинаково на любых языках от C# до php. Ищем там описание кода для любого символа:

Как мы видим, в регулярке за любой символ отвечает точка (.), самая обыкновенная черная точка. Вот ее мы и укажем после href=""

Ничего? Да, все верно, регулярка не работает, (ожидаемо). А все потому, что мы указали 1 символ. То есть, если указать в атрибуте href всего 1 символ, то он выражение сработает. Давайте убедимся в этом:

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

И так, за повторения отвечает или звездочка или знак плюса. Причем разница между ними есть. Выражение со звездочкой будет работать даже если символа вообще нет в анализируемом документе. Берем любой из них, я бы советовал вам взять для начала звездочку. Со временем научитесь их применять в зависимости от ситуации.

Ура! Заработало. Таким образом можно сказать мы написали наше первое регулярное выражение. Но не будем торопиться, ибо нет предела совершенству. Предположим, что нам надо получить из текста именно ту часть которая находится между кавычками. Делает ли это наше выражение? Нет. Оно получает полностью весь блок. Дабы убедиться наведем на мышь на выделенный текст:

То есть задача еще не выполнена. Снова открываем справочник и ищем как захватить часть регулярного выражения.

Простые кавычки () позволяют нам это сделать, хотя описание в документации как всегда крайне поехавшее. Укажем кавычки в нашем редакторе и посмотрим на результат.

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

В php эта регулярка переносится так:

/href="(.*)"/

Ленивые и Жадные квантификаторы

Собственно разница между этими квантификаторами в подходе к выборке данных. Жадное квантификаторы берут Максимально возможный текстовый блок. А Ленивые хапают то, до чего быстрее всего дотягиваются. Ибо остальное собирать — «лень».
В нашем случае ленивое регулярное выражение выглядит так:

/href="(.*?)"/

Я добавил знак вопроса после звездочки. Читаем:

Дабы осветить эту тему на примере нам придется открыть php sandbox, которая позволяет запускать php код прямо из браузера.

Код который мы будем запускать приведен ниже:

// Дублируем дважды нашу ссылку
$str = '<a href="http://aftamat4ik.ru">Это ссылка из которой мы будем брать href</a>
<a href="http://aftamat4ik.ru">Это ссылка из которой мы будем брать href</a>
'; 
// Жадно 
preg_match('/href="(.*)"/is', $str, $matches); 
echo "Жадное регулярное выражение: ".$matches[1].PHP_EOL;; echo '-------------------------'.PHP_EOL; 

// Лениво 
preg_match('/href="(.*?)"/', $str, $matches); echo "Ленивое регулярное выражение: ".$matches[1].PHP_EOL;

Результат выполнения этого кода наглядно покажет вам отличия жадного и ленивого выражения друг от друга.

Как вы видите, без вопросительного знака в коде регулярного выражения нам никак не обойтись, ибо без него выражение будет захватывать лишнюю информацию, превращая все в трэш угар и содомию.

/href="(.*?)"/

Но это еще не все!

Унифицируем регулярное выражение.

Переключимся назад к RegExr и представим ситуацию, при которой html код, анализируемый нами, содержит в href не только двойные, но и одинарные кавычки.

Не работает! Подходящий способ решения — это указать вместо кавычек, набор символов, где будут оба вида этих элементов. За создание набора символов отвечают квадратные скобки:

Собственно делается это так: ["'] — эта последовательность символов соответствует как " и так и '.
Итоговое регулярное выражение примет вид:

/href=['"](.*?)['"]/

Как вы видите, все определяется правильно. Но, обратите внимание на последнюю ссылку, где имеется href=' и ", то есть совершенно не работающий html код, который, тем не менее, определяется как работающий. Что делать, если его надо исключить? Используем ссылки.

Ссылки в регулярных выражениях

Ссылки позволяют нам, в самом выражении, ссылаться на его элементы. Например наш элемент — href="" имеет два повторяющихся символа, на которые мы и будем опираться. Это " и " или ' и '. Так как они повторяются, мы можем взять такой символ и сослаться на него второй раз, а не указывать снова. Тогда получится отфильтровать ошибку, ведь если мы ссылаемся на кавычку вида " то регулярное выражение будет искать именно ее. Чтобы сослаться, надо просто указать конструкцию вида: число, к примеру 1 где цифра — номер скобочки. Да, элемент на который мы ссылаемся, должен быть в круглых скобках. В нашем случае:
Берем выражение ['"] и оборачиваем в кавычки (['"]) а потом просто ссылаемся на кавычки через 1
В итоге получим:

/href=(['"])(.*?)1/

Ура! Последняя строчка не учитывается.

В 90% случаев этих знаний вам хватит с лихвой для парсинга чего угодно, откуда угодно.

Пример парсинга информации

Давайте, используя регулярные выражения и php, спарсим, в маленьком скрипте, например, эту страницу — хабр. Для отработки навыков самое оно будет.

В php за работу регулярок отвечают функции preg_match и preg_match_all, которые и будут использоваться в данном примере.

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

Я работаю в браузере гугл хром, поэтому открываю html-код страницы и ищу там блок с материалом.

и далее сюда —

Тут выделен блок, отвечающий за название материала, которое мы и будем парсить в первую очередь. Чтож, берем его, копируем его в regexr и подбираем регулярное выражение!

Как вы видите в Group#1 находится чистый заголовок. Разберем то, что я написал в выражении:

/class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>/

Элемент (.+?), представляющий из себя строку не нулевой длинны, обрамленный спереди в строку с атрибутом class содержащий блок post__title-arrow и любые .+ символы после этого блока, а так-же два элемента </span> и <span>, разделенные меж собой последовательностью из переноса строки, таба и пробела повторенных несколько раз [nst]+? заканчивается на </span> Да… описание работы выглядит как … в общем не пытайтесь это повторить.

preg_match("/class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>/",$html, $titles);

К стати в блоке ['"] символ означает экранирование кавычки. Он не учитывается в итоговом выражении и всего-лишь помогает интерпретатору воспринимать строку целиком. Осталось вставить эту регулярку в php с экранированием и обрамлением в символы границ.

Итоговый php код выглядит так:

$html = file_get_contents("https://habrahabr.ru/sandbox/15940/");
preg_match("~class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>~",$html,$titles);

echo $titles[1];

Функция preg_match анализирует строку $html и ищет там блок, который подходит под регулярное выражение, после чего извлекает из этого блока группы в круглых скобочках () и помещает их в массив. В данном случае этот массив называется $titles и $titles[1] собственно вывод первой(и единственной в данном случае) кавычки.
И результат выполнения кода выглядит так:

Точно так-же определяем регулярное выражение для текста статьи. Опять копирем блок отвечающий за данный текст в regexr и подбираем выражение, а потом просто вставляем его в preg_match с экранированием.

И выражение:

/class=['"]content html_format['"]>([sS]+?)<div class=['"]post__tags/

Тут вы видите новый блок [sS]+?, что он значит? Заголовок статьи — не имеет в себе переносов строки и поэтому там можно было справиться банальным повторением символа .+? тут же у нас есть переносы и пробелы. Ибо это контент. Чтобы решить проблему мы просто помещаем внутрь кавычек символ s — пробела и S — все что угодно, кроме пробела и указывам, что этот блок повторяется несколько раз через +?

Результат парсинга будет таков —

И вот мы спарсили сайт! Да, так это работает. Человек, потративший пару дней на изучение регулярок, в последствии сможет спарсить все что угодно!

Ну и на последок, разумеется, общий код.


// Тестовый парсер
header('Content-Type: text/html; charset=utf-8');

// Определяем заголовок материала
$html = file_get_contents("https://habrahabr.ru/sandbox/15940/");

preg_match("~class=['"]post__title-arrow.+</span>[nst]+?<span>(.+?)</span>~",$html,$titles);
preg_match("~class=['"]content html_format['"]>([sS]+?)<div class=['"]post__tags~",$html,$contents);

echo "<h3>".$titles[1]."</h3>";
echo $contents[1];

С небольшими отличиями, регулярные выражения одинаковы везде. В js,php,c# или любом другом языке программирования. Синтаксис везде один и тот-же, а значит и этот метод будет актуален и там тоже. К слову, несмотря на все свистопляски с regexr,которые я тут описал, опытный кодер способен написать регулярку на лету, не заморачиваясь. Учитесь, хехе.
Ну и, разумеется, вот исходник, если вам интересно:

Запись Регулярные выражения для чайников впервые появилась Личный блог Гарри.

Источник

Комментарии:

Войдите или зарегистрируйтесь чтобы оставить комментарий

Добавить комментарий