У меня есть значение, подобное этому:
"Foo Bar" "Another Value" something else
Что regex вернет значения, заключенные в кавычки (например, Foo Bar
и Another Value
)?
У меня есть значение, подобное этому:
"Foo Bar" "Another Value" something else
Что regex вернет значения, заключенные в кавычки (например, Foo Bar
и Another Value
)?
Я успешно использовал следующее:
(["'])(?:(?=(\\?))\2.)*?\1
Он также поддерживает вложенные кавычки.
Для тех, кто хочет получить более глубокое объяснение того, как это работает, здесь объяснение от пользователя ephemient:
([""'])
соответствует цитате;((?=(\\?))\2.)
если существует обратная косая черта, сожрать ее, и происходит ли это, соответствует ли символ;*?
много раз встречаются (не жадно, чтобы не есть заключительную цитату);\1
соответствует той же цитате, которая использовалась для открытия.
В общем, следующий фрагмент регулярного выражения - это то, что вы ищете:
"(.*?)"
Это использует не-жадные *? оператора, чтобы захватить все до, но не включая следующую двойную кавычку. Затем вы используете механизм, специфичный для языка, для извлечения совпадающего текста.
В Python вы можете сделать:
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
Я бы пошел за:
"([^"]*)"
[^ "] является регулярным выражением для любого символа, кроме '" '
Причина, по которой я использую это по отношению к не жадному многим операторам, заключается в том, что я должен постоянно следить за этим, чтобы убедиться, что я правильно понял.
Давайте рассмотрим два эффективных способа, которые касаются экранированных кавычек. Эти шаблоны не предназначены для краткости и эстетики, но для эффективности.
Эти способы используют первое распознавание символов для быстрого поиска котировок в строке без затрат на чередование. (Идея состоит в том, чтобы быстро отбросить символы, которые не являются кавычками, без проверки двух ветвей чередования.)
Контент между кавычками описывается с помощью развернутого цикла (вместо повторного чередования), чтобы быть более эффективным: [^"\\]*(?:\\.[^"\\]*)*
Очевидно, что для обработки строк, которые не имеют сбалансированных кавычек, вместо этого вы можете использовать притяжательные кванторы: [^"\\]*+(?:\\.[^"\\]*)*+
или обходной путь для имитации их, чтобы предотвратить слишком много возврата. Вы также можете выбрать, что цитируемая часть может быть открывающей цитатой до следующей (неэкспертированной) цитаты или конца строки. В этом случае нет необходимости использовать притяжательные квантификаторы, вам нужно только сделать последнее предложение необязательным.
Обратите внимание: иногда кавычки не сбрасываются с помощью обратного слэша, но повторяя цитату. В этом случае подшаблон содержимого выглядит так: [^"]*(?:""[^"]*)*
Шаблоны избегают использования группы захвата и обратной ссылки (я имею в виду что-то вроде (["']).....\1
) и используют простое чередование, но с ["']
в начале, в коэффициенте.
Perl вроде:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(обратите внимание, что (?s:...)
является синтаксическим сахаром для включения режима dotall/singleline внутри группы, не содержащей захвата. Если этот синтаксис не поддерживается, вы можете легко включить этот режим для всего шаблона или заменить точку на [\s\S]
)
(Способ написания этого шаблона полностью "ручным" и не учитывает возможные внутренние оптимизации двигателя)
ECMA script:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX расширен:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
или просто:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
Очень поздний ответ, но хотелось бы ответить
(\"[\w\s]+\")
В частности, ни один из этих ответов не создает регулярное выражение, где возвращаемое совпадение является текстом внутри кавычек, и это то, о чем просят. MA-Madden пытается, но получает только внутренний матч как захваченную группу, а не весь матч. Один из способов сделать это:
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
Примеры этого можно увидеть в этой демонстрации https://regex101.com/r/Hbj8aP/1
Ключевым моментом здесь является положительный lookbehind в начале (?<=
) И положительный lookahead в конце (the ?=
). Lookbehind смотрит за текущим персонажем, чтобы проверить цитату, если она будет найдена, тогда начните оттуда, а затем lookahead проверит символ впереди для цитаты и, если будет найден, остановится на этом символе. Группа lookbehind (["']
) заключена в квадратные скобки для создания группы в зависимости от того, какая цитата была найдена в начале, затем она используется в конце просмотра (?=\1)
чтобы убедиться, что она останавливается только тогда, когда она находит соответствующую цитату.
Единственное другое осложнение состоит в том, что, поскольку lookahead фактически не потребляет конечную цитату, он будет снова найден с помощью начального lookbehind, который вызывает текст между окончанием и стартом кавычек в той же строке, которая должна быть сопоставлена. Помещение границы слова в открывающей цитате (["']\b
) помогает с этим, хотя в идеале я бы хотел пройти мимо взгляда, но я не думаю, что это возможно. Бит, позволяющий экранированным символам в середине я "Я взял прямо из ответа Адама.
RegEx принятого ответа возвращает значения, включая их кавычки: "Foo Bar"
и "Another Value"
в качестве совпадений.
Вот RegEx, которые возвращают только значения между кавычками (как задавал вопрошающий):
Только двойные кавычки (используйте значение группы захвата # 1):
"(.*?[^\\])"
Одиночные кавычки (используйте значение группы захвата # 1):
'(.*?[^\\])'
Оба (используйте значение группы захвата # 2):
(["'])(.*?[^\\])\1
-
Все поддерживаемые экранированные и вложенные кавычки.
Эта версия
управляет обратным трассировкой
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
Образец (["'])(?:(?=(\\?))\2.)*?\1
выше выполняет эту работу, но я обеспокоен ее выступлениями (это неплохо, но может быть лучше). Шахта ниже нее ~ на 20% быстрее.
Шаблон "(.*?)"
просто неполный. Мой совет для всех, кто это читает, просто НЕ ИСПОЛЬЗУЙТЕ ЭТО!!!
Например, он не может захватить много строк (при необходимости я могу предоставить исчерпывающий тестовый файл), как показано ниже:
$string = 'Как дела? я
\'
отлично, спасибо;
Остальные из них так же хороши, как и выше.
Если вы действительно заботитесь о производительности и точности, начните с ниже:
/(['"])((\\\1|.)*?)\1/gm
В моих тестах он охватывал каждую строку, которую я встретил, но если вы найдете что-то, что не работает, я бы с радостью обновил ее для вас.
Мне понравилась 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
string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)
просто попробуйте это, работает как шарм!!!
\
указывает символ пропуска
БОЛЬШЕ ОТВЕТОВ! Вот решение, которое я использовал
\"([^\"]*?icon[^\"]*?)\"
TL;DR;
замените слово значок тем, что вы ищете в указанных цитатах и вуаля!
Как это работает, он ищет ключевое слово и не заботится о том, что еще между кавычками.
EG: id="fb-icon"
id="icon-close"
id="large-icon-close"
регулярное выражение ищет метку кавычки "
то он ищет любую возможную группу букв, которая не является "
пока не найдет icon
и любую возможную группу букв, которая не является "
он затем ищет закрытие "
Мне понравилось решение Eugen Mihailescu для сопоставления содержимого между кавычками, позволяя избежать цитат. Однако я обнаружил некоторые проблемы с экранированием и придумал следующее регулярное выражение, чтобы исправить их:
(['"])(?:(?!\1|\\).|\\.)*\1
Он делает трюк и все еще довольно прост и удобен в обслуживании.
Демо (с несколькими тестовыми примерами, не стесняйтесь использовать его и расширять).
PS: Если вам просто нужен контент между котировками в полном совпадении ($0
) и вы не боитесь штрафа за производительность, используйте:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
PPS: Если вы сосредоточены исключительно на эффективности, обратитесь к решению Casimir et Hippolyte; это хороший.
От Greg H. Я смог создать это регулярное выражение в соответствии с моими потребностями.
Мне нужно было сопоставить определенное значение, которое было квалифицировано, находясь внутри кавычек. Это должно быть полное совпадение, никакое частичное совпадение не должно приводить к удару
например. "test" не может соответствовать "test2".
reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."
Хантер
В отличие от ответа Адама, у меня есть простой, но проработавший:
(["'])(?:\\\1|.)*?\1
И просто добавьте круглые скобки, если вы хотите получить контент в кавычках следующим образом:
(["'])((?:\\\1|.)*?)\1
Тогда $1
соответствует кавычки char и $2
соответствует строке содержимого.
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'
Это приведет к: > Foo Bar < > < > , но это & lt;
Здесь я показал строку результата между > < для ясности, также используя нежеланную версию с этой командой sed, мы сначала выкидываем мусор до и после этого ", а затем заменяем это на часть между" "и окружаем ее с помощью > <.
Для меня это сработало:
|([\'"])(.*?)\1|i
Я использовал в таком предложении, как этот:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
и он отлично работал.
Если вы пытаетесь найти строки, содержащие только определенный суффикс, например синтаксис точек, вы можете попробовать следующее:
\"([^\"]*?[^\"]*?)\".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"
.
Дополнительный ответ для подмножества кодеров 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