Поскольку я новичок в регулярных выражениях; Я хочу сделать регулярное выражение для выбора двух последовательных слов.
Например, когда я даю эту фразу: «Привет, люди #RegularExpression сосет!»
Он должен вернуть эти слова:
-Хорошие люди
-people #RegularExpression
– # RegularExpression сосет!
Я попробовал это /\w\s\w/i
но это не сработало 🙁
$s = "Hello people #RegularExpression sucks!"; preg_match_all('~(?=(\S+\s+\S+))\S+\s+~', $s, $matches); print_r($matches[1]);
вывод:
Array ( [0] => Hello people [1] => people #RegularExpression [2] => #RegularExpression sucks! )
объяснение:
\S+
соответствует одному или нескольким символам без пробелов. Ваш \w
был неправильным по двум причинам: он соответствует только одному символу; и он соответствует только так называемому символу слова (эквивалентному [A-Za-z0-9_]
). Добавление этого параметра в ваш тестовый пример не обязательно, но нет причин не добавлять его, а лишние пробелы имеют способ проникнуть в текст в реальном мире. (Но будьте уверены и добавьте +
, а не *
; там должен быть хотя бы один пробельный символ).
(?=...)
является положительным взглядом . Вы используете их, чтобы проверить, возможно ли соответствовать вложенному подвыражению в текущей позиции совпадения, не продвигая позицию соответствия. Затем, как правило, вы идете вперед и сопоставляете другое подвыражение, а не в виде.
Вот сложный бит: хотя символы, совпадающие с подвыражением lookahead, не потребляются , любые группы захвата в подвыражении работают как обычно. Представление в моем регулярном выражении (?=(\S+\s+\S+))
соответствует и фиксирует следующую последовательность из двух слов. Затем (при условии, что просмотр выполнен успешно) \S+\s+
соответствует обычным образом, правильно установив позицию соответствия для следующей попытки.
Этот метод должен работать в любом регулярном выражении, который поддерживает захват групп и взглядов. Это включает в себя PHP, а также все другие основные языки (Perl, JavaScript, .NET, Python, Java …). Метод доступа только к содержимому первой группы захвата из каждого матча сильно варьируется от одного языка к другому, но PHP упрощает его с помощью $matches[1]
.
Ваше регулярное выражение фактически соответствует двум буквам, разделенным пробелом. Таким образом, с вашим вводом вы получите op
и ns
. Другая проблема с этим делает глобальный поиск регулярных выражений в строке возвращает неперекрывающиеся экземпляры. Таким образом, правильное регулярное выражение может возвращать Hello people
, #RegularExpression sucks!
, но он не будет возвращать people #RegularExpression
поскольку это перекрывается с Hello people
. Третий вопрос: как вы определяете слово? Классическое определение, используемое атомом \w
, является буквенно-цифровым или подчеркивающим. Таким образом, #RegularExpression
не будет соответствовать, потому что #
не является символом слова.
В целом, похоже, что вы действительно хотите сделать, просто разделите свою строку на пробелы, а затем вы можете собрать все пары слов самостоятельно. Вы можете сделать раскол с чем-то вроде preg_split('/\s+/', $str)
чтобы вернуть массив всех слов, разделенных пробелами, и затем вы можете перебирать массив, как хотите.
Я уверен, что это возможно сделать с регулярным выражением, но рассол здесь – регулярные выражения, которые потребляют часы, которые они соответствуют, поэтому «вернуться», чтобы получить совпадающие совпадения, является сложной задачей. Regex не подходит для этого; молоток не сосать, потому что он не может (правильно) отрегулировать винты.
Если бы я был вами, я бы просто сделал:
$str = "Hello people #RegularExpression does not suck!"; $arr = explode(' ', $str); for ($i=0; $i<count($arr) - 1; $i++) { echo implode(' ', array_slice($arr, $i, 2)) . "\n"; }
Выходы:
Hello people people #RegularExpression #RegularExpression does does not not suck!
Как и другие, это кажется невозможным ( EDIT: Ой, это неправильно, см. Ответ Алана ) в стандартном регулярном выражении pcre, и вам лучше выбрать другую стратегию.
Позвольте мне добавить, что, похоже, существует экспериментальное и сложное решение: глаголы отступания.
См. Раздел «УПРАВЛЕНИЕ РЕГУЛИРОВКОЙ» в документе pcre.org/pcre.txt
Эта модель должна работать:
/[^\s]+\s[^\s]+/i
Соответствует каждому пробелу, за которым следует одиночный символ пробела и другие символы без пробелов.