Відповіді:
Я з великим успіхом використовував наступне:
(["'])(?:(?=(\\?))\2.)*?\1
Він також підтримує вкладені цитати.
Для тих, хто хоче більш глибоке пояснення того, як це працює, ось пояснення від користувальницьких ефеміент :
([""'])
відповідати цитаті;((?=(\\?))\2.)
якщо зворотний косий рядок існує, погладьте його, і чи це трапляється, відповідати символу;*?
збігайтеся багато разів (не жадібно, щоб не з'їсти заключну цитату);\1
збігаються з тією ж цитатою, яка була використана для відкриття.
"foo\"
. Трюк вперед робить ?
квантор нав'язливим (навіть якщо аромат регулярного виразів не підтримує ?+
синтаксис чи атомну групування)
(["'])(?:\\.|[^\\])*?\1
Загалом, ви шукаєте наступний фрагмент регулярного виразу:
"(.*?)"
Для цього використовується негнійний *? оператор, щоб зафіксувати все, але не включаючи наступну подвійну пропозицію. Потім ви використовуєте специфічний для мови механізм для вилучення відповідного тексту.
У Python ви можете:
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
"hello \" world"
"(.*?(?<!\\))"
Я б пішов на:
"([^"]*)"
[^ «] Є регулярним виразом для будь-якого символу , крім ' » '
Причини , я використовую це за відсутність жодних багатьох операторів в тому , що я повинен продовжувати дивитися , що тільки , щоб переконатися , що я отримую це виправити.
Давайте побачимо два ефективні способи, що стосуються втеклих цитат. Ці схеми розроблені не для того, щоб бути стислими або естетичними, а бути ефективними.
Ці способи використовують дискримінацію першого символу для швидкого пошуку цитат у рядку без вартості чергування. (Ідея полягає в тому, щоб швидко відкинути символи, які не є цитатами, не перевірити дві гілки чергування.)
Вміст між цитатами описується циклом, який не розгортається (замість повторного чергування), щоб бути більш ефективним: [^"\\]*(?:\\.[^"\\]*)*
Очевидно, щоб мати справу з рядками, які не мають врівноважених лапок, ви можете використовувати замість них присвійні квантори: [^"\\]*+(?:\\.[^"\\]*)*+
або обхід, щоб імітувати їх, щоб запобігти занадто сильному зворотному відстеженню. Ви також можете вибрати, що частина, що цитується, може бути початковою цитатою до наступної (не уникнутої) цитати або до кінця рядка. У цьому випадку немає необхідності використовувати присвійні кількісні показники, потрібно лише зробити останню цитату необов’язковою.
Зверніть увагу: іноді цитати не виходять із зворотним нахилом, а повторенням цитати. У цьому випадку підмітка вмісту виглядає приблизно так:[^"]*(?:""[^"]*)*
Шаблони уникають використання групи захоплення та зворотної референції (я маю на увазі щось подібне (["']).....\1
) і використовують просте чергування, але ["']
на початку, в факторі.
Перл як:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(зауважте, що (?s:...)
це синтаксичний цукор, щоб увімкнути режим "доталл / одиночний рядок" у групі, що не захоплює. Якщо цей синтаксис не підтримується, ви можете легко увімкнути цей режим для всіх шаблонів або замінити крапку на [\s\S]
)
(Спосіб написання цієї схеми повністю "керований вручну" і не враховує можливих внутрішніх оптимізацій двигуна)
Сценарій ECMA:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX розширено:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
або просто:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
/pattern/
не уникаючи нічого (замість позначення об'єкта new RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");
)
s
тут: (?s:
і якщо ви поставите (?s)
десь у шаблоні.
RegEx прийнятої відповіді повертає значення, включаючи їхні окружні лапки: "Foo Bar"
і "Another Value"
як збіги.
Ось RegEx, який повертає лише значення між лапками (як запитував запитувач):
Лише подвійні лапки (використовуйте значення групи захоплення №1):
"(.*?[^\\])"
Лише окремі котирування (використовуйте значення групи захоплення №1):
'(.*?[^\\])'
Обидва (використовувати значення групи захоплення №2):
(["'])(.*?[^\\])\1
-
Вся підтримка втекла і вклалася цитатами.
src="(.*)"
але очевидно, він вибирав все до останнього ", ваш REGEX, хоча, вибрав лише вміст src =" ", але я не зрозумів як?
Своєрідно, жодна з цих відповідей не створює регулярного вираження, де повернене збіг - це текст всередині лапок, про що і вимагається. MA-Madden намагається, але отримує лише внутрішній матч як захоплену групу, а не весь матч. Один із способів насправді зробити це:
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
Приклади цього можна побачити в цьому демонстраційному https://regex101.com/r/Hbj8aP/1
Ключовим тут є позитивний погляд ззаду на початку (the ?<=
) і позитивний lookahead в кінці (the ?=
). Подивившись дивиться позаду поточного символу, щоб перевірити наявність цитати, якщо його знайдуть, тоді почніть звідти, і тоді lookahead перевіряє персонажа вперед на ціну, і якщо знайдено зупинку на цьому символі. Група, що дивиться назад ( ["']
), загорнута в дужки, щоб створити групу, яка б цитата була знайдена на початку, вона потім використовується в кінці пошуку, (?=\1)
щоб переконатися, що вона зупиняється лише тоді, коли вона знайде відповідну цитату.
Єдине інше ускладнення полягає в тому, що оскільки lookahead насправді не споживає кінцеву цитату, вона знову знайдеться за допомогою початкового огляду, за яким текст між кінцевим і початковим лапки в одному рядку буде збігатися. Якщо ввести початкову цитату слова ( ["']\b
), це допомагає в цьому, хоча в ідеалі я хотів би пройти повз шуму, але я не думаю, що це можливо. Біт, що дозволяє уникнути символів посередині, я взяв прямо з відповіді Адама.
Наведена (["'])(?:(?=(\\?))\2.)*?\1
вище картина виконує цю роботу, але мене турбують її виступи (це не погано, але може бути і краще). У мене нижче ~ 20% швидше.
Шаблон "(.*?)"
просто неповний. Моя порада для всіх, хто читає це, просто НЕ ВИКОРИСТОВУЙТЕ !!!
Наприклад, він не може зафіксувати багато рядків (якщо потрібно, я можу надати вичерпний тестовий зразок), як описано нижче:
$ string = 'Як справи? Я
\'
добре, дякую ';
Решта з них такі ж «хороші», як і вище.
Якщо ви дійсно дбаєте про продуктивність та точність, почніть з наведеного нижче:
/(['"])((\\\1|.)*?)\1/gm
У моїх тестах вона охоплювала кожну зустріч, яку я зустрічав, але якщо ви знайдете щось, що не працює, я з радістю оновив би це для вас.
Мені сподобалося рішення Євгена Михайлеску відповідати вмісту між цитатами, дозволяючи уникати цитат. Однак я виявив деякі проблеми з втечею і придумав наступний регулярний вираз, щоб їх виправити:
(['"])(?:(?!\1|\\).|\\.)*\1
Це робить трюк і все ще досить простий і простий у обслуговуванні.
Демо (з деякими ще тестовими кейсами; сміливо використовуйте його та розширюйте його).
PS: Якщо ви просто хочете, щоб вміст між цитатами в повному матчі ( $0
), і ви не боїтеся використання покарання за виконання, виконайте такі дії:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
На жаль, без лапок в якості якорів мені довелося додати межу, \b
яка не добре розігрується з пробілами та немедними символами меж після початкової лапки.
Крім того, змініть початкову версію, просто додавши групу та витягніть форму рядка$2
:
(['"])((?:(?!\1|\\).|\\.)*)\1
PPS: Якщо ваша увага зосереджена виключно на ефективності, перейдіть до рішення Казимира та Іполита ; це добре.
-
, як у координатах довготи.
Ця версія
контролює зворотний трек
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
БІЛЬШЕ ВІДПОВІДЬ! Ось рішення, яке я використав
\"([^\"]*?icon[^\"]*?)\"
TLDR;
замініть піктограму слова на те, що шукаєте у зазначених цитатах та вуалі!
Як це працює, це шукає ключове слово і не байдуже, що ще між цитатами. EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
регулярний вираз шукає лапки, "
тоді він шукає будь-яку можливу групу листів, "
поки не знайде, icon
і будь-яка можлива група букв, яка не є, "
тоді шукає закриття"
name="value"
з, name={"value"}
оскільки регекс цієї відповіді повертається icon
/ value
як друга група (на відміну від прийнятої відповіді). Знайдіть : =\"([^\"]*?[^\"]*?)\"
Замініть :={"$1"}
Мені сподобалася більш розширена версія 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)
просто спробуйте це, працює як шарм !!!
\
вказує на пропуск символів
" foo bar" "loloo"
. Я підозрюю , що ви мали в виду , щоб обернути , що в сирому рядок , як ви робили з регулярним виразом: r'"\" foo bar\" \"loloo\""'
. Будь ласка, використовуйте чудові можливості форматування SO, коли це доречно. Це не просто косметика; ми буквально не можемо сказати, що ви намагаєтесь сказати, якщо ви не використовуєте їх. І ласкаво просимо до Stack Overflow !
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'
Це призведе до:> Foo Bar <> <> but this <
Тут я показав рядок результатів між> <'s для ясності, також, використовуючи не жадібну версію за допомогою цієї команди sed, ми спочатку викидаємо барахло до і після цього, а потім замінюємо цю частину між "" і оточують це за допомогою <<s.
Від Грега Х. мені вдалося створити цей регекс відповідно до моїх потреб.
Мені потрібно було відповідати конкретному значенню, яке було кваліфіковане тим, що знаходяться всередині лапок. Це має бути повноцінна відповідність, жодна часткова відповідність не може спричинити удар
наприклад, "test" не міг відповідати "test2".
reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."
Мисливець
Якщо ви намагаєтеся знайти рядки з лише певним суфіксом, наприклад синтаксисом крапок, ви можете спробувати це:
\"([^\"]*?[^\"]*?)\".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"
.
Додаткову відповідь для підмножини кодерів 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
Для мене працював цей:
|([\'"])(.*?)\1|i
Я використовував таке речення:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
і це чудово працювало.
Усі відповіді вище хороші .... за винятком того, що вони НЕ підтримують усіх символів unicode! на сценарії ECMA (Javascript)
Якщо ви користувачі Вузла, можливо, ви захочете модифіковану версію прийнятої відповіді, яка підтримує всі символи unicode:
/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu
Спробуйте тут .
? The preceding token is not quantifiable