2008-10-05 4 views
133

У меня есть значение как это:RegEx: Схватив значения между кавычками

"Foo Bar" "Another Value" something else 

Что регулярное выражение будет возвращать значения, заключенные в кавычки (например Foo Bar и Another Value)?

+0

Связано с http://stackoverflow.com/questions/138552/can-regex-be-used-for-this-particular-string-manipulation – 2008-10-05 09:56:08

ответ

223

Я использую следующий с большим успехом:

(["'])(?:(?=(\\?))\2.)*?\1 

Он поддерживает вложенные кавычки, а также.

Для тех, кто хочет более глубокое объяснение того, как это работает, вот объяснение от пользователя ephemient:

([""']) match a quote; ((?=(\\?))\2.) if backslash exists, gobble it, and whether or not that happens, match a character; *? match many times (non-greedily, as to not eat the closing quote); \1 match the same quote that was use for opening.

+4

Не могли бы вы дать некоторое объяснение тому, как оно читается - это было бы очень полезно - Спасибо – philant 2008-10-05 12:41:22

+9

(["" ']) соответствуют цитате; ((? = (\\?)) \ 2.) Если существует обратная косая черта, сожрать ее, и происходит ли это, соответствует ли символ; *? много раз встречались (не жадно, чтобы не дожидаться заключительной цитаты); \ 1 соответствуют той же цитате, которая использовалась для открытия. – ephemient 2008-10-06 05:17:31

+14

Это также работает: `([" ']) (\\ ?.) *? \ 1' Легче читать. – steve 2014-03-03 19:18:30

217

В общем, следующем регулярном выражении фрагмент является то, что вы ищете:

"(.*?)" 

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

В Python, вы можете сделать:

>>> import re 
>>> string = '"Foo Bar" "Another Value"' 
>>> print re.findall(r'"(.*?)"', string) 
['Foo Bar', 'Another Value'] 
+7

Это замечательно, однако оно не обрабатывает строки с экранированными кавычками. например, `` hello \ "world" ` – robbyt 2015-02-05 20:01:10

+0

Используя совпадение JavaScript, это также будет соответствовать кавычкам. Оно будет работать с итерацией над exec, как описано здесь: http://stackoverflow.com/questions/7998180/regex-how -to-extract-text-from-between-quotes-and-exclude-quotes – Kiechlus 2016-04-27 12:22:52

+2

@robbyt Я знаю, что немного поздно для ответа, но как насчет отрицательного вида? "(. *? (? Mateus 2017-07-07 18:39:41

66

Я хотел бы пойти на:

"([^"]*)" 

[^ "] является регулярное выражение для любого символа, кроме '" "
Причина, по которой я использую это по отношению к не жадному многим операторам, заключается в том, что я должен постоянно следить за этим, чтобы убедиться, что я правильно понял.

+0

Это также хорошо относится к различным интерпретациям регулярных выражений. – 2008-10-05 14:33:48

+5

Это спасло мое здравомыслие. В реализации RegEx .NET, (. *?) "не имеет желаемого эффекта (он не действует не жадным), но" ([^ "] *)" делает. – 2013-09-18 09:52:27

0
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g' 

Это приведет к:> Foo Bar <> <> но это <

Здесь я показал строку результата между> < для ясности, также используя не жадную версию с этой командой sed, мы сначала выбрасываем мусор до и после этого, а затем replac e это с частью между «" и окружает это с помощью <.

6

Эта версия

  • счета для уцелевших котировок
  • управления возвратов

    /(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/ 
    
0

Для меня работал этот:

|([\'"])(.*?)\1|i 

Я использовал в таком предложении, как этот:

preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches); 

и он отлично работал.

1

От Greg H.Я смог создать это регулярное выражение в соответствии с моими потребностями.

Мне нужно было соответствовать определенному значению, которое было определено, находясь внутри кавычек. Это должно быть полное совпадение, никакое частичное совпадение не должно приводить к удару

например. «test» не может соответствовать «test2».

reg = r"""(['"])(%s)\1""" 
if re.search(reg%(needle), haystack, re.IGNORECASE): 
    print "winning..." 

Hunter

3

мне понравилась больше экспансивной версия лесоруб, но были некоторые проблемы с ним (это не соответствует, например

foo "string \\ string" bar 

или

foo "string1" bar "string2" 

правильно, поэтому я попытался исправить это:

# opening quote 
(["']) 
    (
    # repeat (non-greedy, so we don't span multiple strings) 
    (?: 
     # anything, except not the opening quote, and not 
     # a backslash, which are handled separately. 
     (?!\1)[^\\] 
     | 
     # consume any double backslash (unnecessary?) 
     (?:\\\\)*  
     | 
     # Allow backslash to escape characters 
     \\. 
    )*? 
    ) 
# same character as opening quote 
\1 
1
string = "\" foo bar\" \"loloo\"" 
print re.findall(r'"(.*?)"',string) 

просто попробуйте это, работает как шарм !!!

\ указывает пропустить персонажу

17

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

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

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

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

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

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

Perl как:

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

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

(путь этого шаблон написан полностью «с ручным приводом» и не учитывает возможный двигатель внутреннего O ptimizations)

ECMA Сценарий:

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

POSIX расширен:

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

или просто:

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

узора (["'])(?:(?=(\\?))\2.)*?\1 выше выполняет эту работу, но я обеспокоен ее выступлениями (это неплохо, но может быть лучше). Мой ниже - на 20% быстрее.

Узор "(.*?)" просто неполный. Мой совет для всех, кто это читает, просто НЕ ИСПОЛЬЗУЙТЕ ЭТО !!!

Например, он не может захватить много строк (при необходимости я могу дать исчерпывающий тест-случай), как показано ниже:

$string = 'How are you? I \' m fine, thank you';

Остальные из них так же, как «хорошо», как один из приведенных выше.

Если вы действительно заботитесь и о производительности и точности, то начните с приведенной ниже:

/(['"])((\\\1|.)*?)\1/gm

В моих тестах она охватывает все строки я встретил, но если вы нашли что-то, что не работает, я бы с радостью обновите его для вас.

Check my pattern in an online regex tester.

4

RegEx принятого ответа возвращает значения, включая их ориентировочные кавычки: "Foo Bar" и "Another Value" в виде совпадений.

Вот RegEx, которые возвращают только значения между кавычки (как спрашивающий просил):

двойные кавычки только (используйте значение группы захвата # 1):

"(.*?[^\\])"

Одинарные кавычки только (используйте значение группы захвата # 1):

'(.*?[^\\])'

Оба (потребительная стоимость 2 группы захвата #):

(["'])(.*?[^\\])\1

-

Вся поддержка спасся и вложенные кавычки.

3

БОЛЬШЕ ОТВЕТОВ! Вот решение я использовал

\"([^\"]*?icon[^\"]*?)\"

TLDR;
заменить слово icon с тем, что вы ищете в указанных цитатах и ​​вуаля!


Как это работает, он ищет ключевое слово и не заботится о том, что еще между кавычками. EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
регулярное выражение ищет кавычки "
то она выглядит для любой возможной группы букв то не "
до тех пор, пока не найдет icon
и любые возможные группы букв то есть не "
затем он ищет закрытие "

3

В частности, ни один из этих ответов не создает регулярное выражение, где возвращаемое совпадение является текстом внутри кавычек, о котором идет запрос. MA-Madden пытается, но получает только внутренний матч как захваченную группу, а не весь матч. Один из способов на самом деле это было бы:

(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1) 

Примеры этого можно увидеть в этой демонстрации https://regex101.com/r/Hbj8aP/1

Ключевым моментом здесь является положительным просмотром назад на старте (?<=) и положительный предпросмотр в конец (?=). Lookbehind смотрит за текущим персонажем, чтобы проверить цитату, если она будет найдена, тогда начните оттуда, а затем lookahead проверит символ впереди для цитаты и, если будет найден, остановится на этом символе.Группа lookbehind (["']) завернута в скобки, чтобы создать группу для какой-либо цитаты, найденной в начале, тогда она используется в конце обзора (?=\1), чтобы убедиться, что она останавливается только при обнаружении соответствующей цитаты.

Единственное другое осложнение состоит в том, что, поскольку lookahead фактически не потребляет конечную цитату, он будет снова найден с помощью начального lookbehind, который вызывает текст между окончанием и стартом кавычек на одной и той же строке, которая должна быть сопоставлена. Помещение границы слова на вводную цитату (["']\b) помогает с этим, хотя в идеале я бы хотел пройти мимо взгляда, но я не думаю, что это возможно. Бит, позволяющий экранированным символам посередине, я взял непосредственно из ответа Адама.

0

Если вы пытаетесь найти строки, которые имеют только определенный суффикс, такие как точечный синтаксис, вы можете попробовать это:

\"([^\"]*?[^\"]*?)\".localized

Где .localized является суффиксом.

Пример:

print("this is something I need to return".localized + "so is this".localized + "but this is not")

Он захватит "this is something I need to return".localized и "so is this".localized, но не "but this is not".

Смежные вопросы