RegEx: присвоение значений между кавычками

У меня есть значение, подобное этому:

"Foo Bar" "Another Value" something else

Что regex вернет значения, заключенные в кавычки (например, Foo Bar и Another Value)?

Ответ 1

Я успешно использовал следующее:

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

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

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

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

Ответ 2

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

"(.*?)"

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

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

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

Ответ 3

Я бы пошел за:

"([^"]*)"

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

Ответ 4

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

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

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

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

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

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

Perl вроде:

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

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

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

ECMA script:

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

POSIX расширен:

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

или просто:

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

Ответ 6

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

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

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

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

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

Ответ 7

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

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

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

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

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

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

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

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

-

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

Ответ 8

Эта версия

  • учитывает скрытые кавычки
  • управляет обратным трассировкой

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

Ответ 9

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

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

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

$string = 'Как дела? я \' отлично, спасибо;

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

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

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

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

Проверьте мой шаблон в онлайн-тесте регулярных выражений.

Ответ 10

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

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

Ответ 11

string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)

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

\ указывает символ пропуска

Ответ 12

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

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

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


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

Ответ 13

Мне понравилось решение Eugen Mihailescu для сопоставления содержимого между кавычками, позволяя избежать цитат. Однако я обнаружил некоторые проблемы с экранированием и придумал следующее регулярное выражение, чтобы исправить их:

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

Он делает трюк и все еще довольно прост и удобен в обслуживании.

Демо (с несколькими тестовыми примерами, не стесняйтесь использовать его и расширять).


PS: Если вам просто нужен контент между котировками в полном совпадении ($0) и вы не боитесь штрафа за производительность, используйте:

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

PPS: Если вы сосредоточены исключительно на эффективности, обратитесь к решению Casimir et Hippolyte; это хороший.

Ответ 14

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

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

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

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

Хантер

Ответ 15

В отличие от ответа Адама, у меня есть простой, но проработавший:

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

И просто добавьте круглые скобки, если вы хотите получить контент в кавычках следующим образом:

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

Тогда $1 соответствует кавычки char и $2 соответствует строке содержимого.

Ответ 16

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

Это приведет к: > Foo Bar < > < > , но это & ​​lt;

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

Ответ 17

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

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

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

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

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

Ответ 18

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

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

Где. .localized - суффикс.

Пример:

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

Он будет захватывать "this is something я need to return".localized и "so is this".localized "this is something я need to return".localized и "so is this".localized но не "but this is not".

Ответ 19

Дополнительный ответ для подмножества кодеров Microsoft VBA только один использует библиотеку Microsoft VBScript Regular Expressions 5.5 и это дает следующий код

Sub TestRegularExpression()

    Dim oRE As VBScript_RegExp_55.RegExp    '* Tools->References: Microsoft VBScript Regular Expressions 5.5
    Set oRE = New VBScript_RegExp_55.RegExp

    oRE.Pattern = """([^""]*)"""


    oRE.Global = True

    Dim sTest As String
    sTest = """Foo Bar"" ""Another Value"" something else"

    Debug.Assert oRE.test(sTest)

    Dim oMatchCol As VBScript_RegExp_55.MatchCollection
    Set oMatchCol = oRE.Execute(sTest)
    Debug.Assert oMatchCol.Count = 2

    Dim oMatch As Match
    For Each oMatch In oMatchCol
        Debug.Print oMatch.SubMatches(0)

    Next oMatch

End Sub