Как строка соответствия регулярному выражению внутри двойных кавычек, но не включая двойные кавычки? [Дубликат]

147
задан Alan Moore 15 March 2014 в 19:32
поделиться

18 ответов

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

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

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

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

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

247
ответ дан Community 17 August 2018 в 10:24
поделиться
  • 1
    Это также работает: (["'])(\\?.)*?\1 Легче читать. – steve 3 March 2014 в 21:18
  • 2
    Вы, сэр, - змеевик с регулярным выражением – dolbysurnd 26 March 2014 в 21:00
  • 3
    @steve: это также неправильно, "foo\". Взгляд вперед трюк делает ? квантором притяжательным (даже если аромат регулярного выражения не поддерживает синтаксис ?+ или атомную группировку) – Robin 11 September 2014 в 14:33
  • 4
    С python это вызывает ошибку: sre_constants.error: не может ссылаться на открытую группу – a1an 12 June 2015 в 10:43
  • 5
    Это возвращает значения, включая соответствующие кавычки. Нет ли шанса вернуть только контент между кавычками, как он был запрошен? – MA-Maddin 13 September 2016 в 11:19

Эта версия

  • учитывает экранированные кавычки
  • управляет обратным трассированием
    /(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
    
6
ответ дан 2 revs, 2 users 91% 17 August 2018 в 10:24
поделиться
  • 1
    Это охватывает несколько строк и, похоже, не обрабатывает двойную обратную косую черту правильно, например строку: foo 'stri \\ng 1' bar 'string 2' и 'string 3' Debuggex Demo – miracle2k 1 October 2013 в 20:30
  • 2
    Вы не можете использовать обратную ссылку в классе символов. – HamZa 30 January 2014 в 03:53
string = "\" foo bar\" \"loloo\""
print re.findall(r'"(.*?)"',string)

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

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

2
ответ дан Alan Moore 17 August 2018 в 10:24
поделиться
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'

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

Здесь я продемонстрировал строку результата между> & lt; s для ясности, также используя неживую версии с этой командой sed, мы сначала выкидываем мусор до и после этого «», а затем заменяем его на часть между «» и окружаем ее с помощью «& lt;».

0
ответ дан amo-ej1 17 August 2018 в 10:24
поделиться

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

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

Содержимое между кавычками описывается с развернутым контуром (вместо повторное чередование): [^"\\]*(?:\\.[^"\\]*)*

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

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

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

Perl like:

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

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

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

Сценарий ECMA:

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

POSIX extended:

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

или просто:

"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
20
ответ дан Casimir et Hippolyte 17 August 2018 в 10:24
поделиться
  • 1
    Есть много людей, которые отвечают на вопросы регулярных выражений, но их мало кто знает, что это такое! ;) Мне нравятся ваши регулярные выражения! – Kasramvd 6 April 2015 в 13:24
  • 2
    Python принимает сценарий ECMA с необработанным строковым форматом, то есть r & quot; & quot; & quot; ECMA-скрипт & quot; "& quot; – a1an 12 June 2015 в 11:00
  • 3
    Это великолепно, очень легко адаптировать ECMA один для работы с экранированием новой строки и возврата каретки внутри двойных кавычек. – Douglas Gaskell 16 April 2016 в 02:27
  • 4
    @ douglasg14b: Спасибо. Обратите внимание, что если вы хотите использовать его в Javascript, вам нужно использовать только буквенную нотацию /pattern/ без экранирования (вместо обозначения объекта new RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");) – Casimir et Hippolyte 17 April 2016 в 17:05
  • 5
    @ a1an: да, но вы можете использовать версию Perl, если вы удалите s здесь: (?s:, и если вы поместите (?s) где-нибудь в шаблон. – Casimir et Hippolyte 17 April 2016 в 17:07

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

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

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

$ string = 'Как вы? I \' m fine, thank you ';

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

Если вам действительно нравятся производительность и точность затем начинаются с одного ниже:

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

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

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

5
ответ дан Eugen Mihailescu 17 August 2018 в 10:24
поделиться
  • 1
    Мне нравится простота вашего шаблона, однако по качеству рисунка Казимира и Ипполита ударяет все расширенные решения из воды. Кроме того, похоже, что ваш шаблон имеет проблемы с расширенными краевыми случаями, такими как экранированная цитата в конце предложения. – wp78de 13 May 2018 в 20:53

Я работал над этим:

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

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

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

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

3
ответ дан HamZa 17 August 2018 в 10:24
поделиться
  • 1
    Слабостью этого подхода является то, что он будет соответствовать, когда строка начинается с одной кавычки и заканчивается двойной кавычкой, или наоборот. – Ghopper21 17 July 2012 в 16:49
  • 2
    У этого также есть проблемы, чтобы поймать "Не забывайте @ & quot; - Он останавливается после «Дон». – Benny Neugebauer 13 January 2014 в 14:26

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

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

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

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

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

7
ответ дан IrishDubGuy 17 August 2018 в 10:24
поделиться

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

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

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


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

2
ответ дан James Harrington 17 August 2018 в 10:24
поделиться
  • 1
    Большое спасибо. смог заменить каждое вхождение name="value" на name={"value"}, поскольку регулярное выражение этого ответа возвращает icon / value как вторую группу (в отличие от принятого ответа). Найти : =\"([^\"]*?[^\"]*?)\" Заменить : ={"$1"} – Palisand 20 September 2017 в 19:24
  • 2
    Ум объясняет нижний план? он хорошо работает из некоторых ситуаций. – James Harrington 10 July 2018 в 16:36
  • 3
    Вы отвечаете мне? – Palisand 10 July 2018 в 21:29
  • 4
    @Palisand никто не пропустил этот пост на днях без объяснения причин. – James Harrington 12 July 2018 в 15:28

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

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

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

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

Затем $1 соответствует quote char и $2 соответствует строке содержимого.

0
ответ дан lon 17 August 2018 в 10:24
поделиться

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

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

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

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

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

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

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

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

-

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

5
ответ дан MA-Maddin 17 August 2018 в 10:24
поделиться
  • 1
    Пожалуйста, почему это работает? Я использовал src="(.*)", но, очевидно, он выбирал все до последнего & quot ;, ваш REGEX, однако, выбрал только src = & quot; & quot; содержимое, но я не понял, как? – Lucas Bustamante 25 July 2018 в 23:25

Я бы хотел:

"([^"]*)"

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

70
ответ дан Martin York 17 August 2018 в 10:24
поделиться
  • 1
    Это также хорошо влияет на различные интерпретации регулярных выражений. – Phil Bennett 5 October 2008 в 15:33
  • 2
    Это спасло мое здравомыслие. В реализации RegEx .NET, & quot; (. *?) & Quot; не имеет желаемого эффекта (он не действует не жадным), но "([^"] *) " делает. – Jens Neubauer 18 September 2013 в 10:52

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

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

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

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

Hunter

1
ответ дан motoprog 17 August 2018 в 10:24
поделиться

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

\"([^\"]*?[^\"]*?)\".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".

0
ответ дан OffensivelyBad 17 August 2018 в 10:24
поделиться

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

"(.*?)"

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

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

>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
238
ответ дан Rodrigo Deodoro 17 August 2018 в 10:24
поделиться
  • 1
    Это замечательно, однако он не обрабатывает строки с экранированными кавычками. например, "hello \" world" – robbyt 5 February 2015 в 21:01
  • 2
    Используя совпадение JavaScript, это также будет соответствовать кавычки. Он будет работать с итерацией над exec, как описано здесь: stackoverflow.com/questions/7998180/… – Kiechlus 27 April 2016 в 12:22
  • 3
    @robbyt Я знаю, что немного поздно ответить, но как насчет негативного взгляда? "(.*?(?<!\\))" – Mateus 7 July 2017 в 18:39
  • 4
    Спасибо, это проще, если вы уверены, что нет никаких скрытых цитат. – squarecandy 2 December 2017 в 20:17

Дополнительный ответ для подмножества кодеров 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
0
ответ дан S Meaden 17 August 2018 в 10:24
поделиться

Очень поздний ответ, но хотелось бы ответить

(\"[\w\s]+\")

http://regex101.com/r/cB0kB8/1

9
ответ дан Suganthan Madhavan Pillai 17 August 2018 в 10:24
поделиться
  • 1
    не работает для меня в Javascript, необходимо прочитать \ & quot; \ w + \ & quot; – iamwhitebox 17 March 2015 в 17:57
  • 2
    Хорошо работает в php. – Parapluie 2 February 2018 в 18:32

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

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

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

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


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

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

PPS: Если ваша фокусировка зависит исключительно от эффективности, перейдите к Решение Казимира и Ипполита ; это хороший.

0
ответ дан wp78de 17 August 2018 в 10:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: