Respostas:
Eu tenho usado o seguinte com grande sucesso:
(["'])(?:(?=(\\?))\2.)*?\1
Ele também suporta aspas aninhadas.
Para aqueles que desejam uma explicação mais profunda de como isso funciona, aqui está uma explicação do efemiente do usuário :
([""'])
corresponder a uma cotação;((?=(\\?))\2.)
se a barra invertida existir, engula e, se isso acontece ou não, combine um caractere;*?
corresponder muitas vezes (sem avidez, para não comer a citação de fechamento);\1
corresponder à mesma citação usada para a abertura.
"foo\"
,. O truque frente olhar faz com que o ?
possessivo quantificador (mesmo se o sabor de regex não suporta a ?+
sintaxe ou atômica agrupamento)
(["'])(?:\\.|[^\\])*?\1
Em geral, o seguinte fragmento de expressão regular é o que você está procurando:
"(.*?)"
Isso usa o não-ganancioso *? operador para capturar tudo, mas sem incluir a próxima cotação dupla. Em seguida, você usa um mecanismo específico do idioma para extrair o texto correspondente.
No Python, você pode fazer:
>>> import re
>>> string = '"Foo Bar" "Another Value"'
>>> print re.findall(r'"(.*?)"', string)
['Foo Bar', 'Another Value']
"hello \" world"
"(.*?(?<!\\))"
Eu iria para:
"([^"]*)"
O [^ "] é regex para qualquer caractere, exceto ' " '
A razão pela qual eu uso isso em muitos operadores não gananciosos é que tenho que continuar pesquisando isso apenas para ter certeza de que está correto.
Vamos ver duas maneiras eficientes de lidar com aspas escapadas. Esses padrões não são projetados para serem concisos nem estéticos, mas para serem eficientes.
Essas maneiras usam a discriminação do primeiro caractere para encontrar rapidamente aspas na string sem o custo de uma alternância. (A idéia é descartar rapidamente caracteres que não são aspas sem testar os dois ramos da alternância.)
O conteúdo entre aspas é descrito com um loop desenrolado (em vez de uma alternância repetida) para ser mais eficiente também: [^"\\]*(?:\\.[^"\\]*)*
Obviamente, para lidar com seqüências de caracteres que não possuem aspas balanceadas, você pode usar quantificadores possessivos: [^"\\]*+(?:\\.[^"\\]*)*+
ou uma solução alternativa para emulá-los, para evitar muitos retrocessos. Você também pode escolher que uma parte entre aspas possa ser uma cotação de abertura até a próxima cotação (sem escape) ou o final da sequência. Nesse caso, não há necessidade de usar quantificadores possessivos, você só precisa tornar a última cotação opcional.
Aviso: às vezes as aspas não são escapadas com uma barra invertida, mas repetindo-a. Nesse caso, o subpadrão de conteúdo fica assim:[^"]*(?:""[^"]*)*
Os padrões evitam o uso de um grupo de captura e uma referência anterior (quero dizer algo como (["']).....\1
) e usam uma alternância simples, mas com ["']
no início, em fator.
Perl gosta:
["'](?:(?<=")[^"\\]*(?s:\\.[^"\\]*)*"|(?<=')[^'\\]*(?s:\\.[^'\\]*)*')
(observe que (?s:...)
é um açúcar sintático para ativar o modo dotall / linha única dentro do grupo que não captura. Se essa sintaxe não for suportada, você poderá facilmente ativar esse modo para todo o padrão ou substituir o ponto [\s\S]
)
(A maneira como esse padrão é escrito é totalmente "manual" e não leva em consideração as eventuais otimizações internas do mecanismo)
Script ECMA:
(?=["'])(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*')
POSIX estendido:
"[^"\\]*(\\(.|\n)[^"\\]*)*"|'[^'\\]*(\\(.|\n)[^'\\]*)*'
ou simplesmente:
"([^"\\]|\\.|\\\n)*"|'([^'\\]|\\.|\\\n)*'
/pattern/
sem escapar nada (em vez da notação de objeto new RegExp("(?=[\"'])(?:\"[^\"\\\\]*...");
)
s
here: (?s:
e se você colocar (?s)
em algum lugar do padrão.
O RegEx da resposta aceita retorna os valores, incluindo suas aspas: "Foo Bar"
e "Another Value"
como correspondências.
Aqui estão RegEx que retornam apenas os valores entre aspas (como o questionador estava pedindo):
Somente aspas duplas (use o valor do grupo de captura nº 1):
"(.*?[^\\])"
Somente aspas simples (use o valor do grupo de captura nº 1):
'(.*?[^\\])'
Ambos (use o valor do grupo de captura nº 2):
(["'])(.*?[^\\])\1
-
Todo o suporte escapou e citações aninhadas.
src="(.*)"
, mas, obviamente, ele estava selecionando tudo antes da última", o seu REGEX, porém, selecionado apenas o src = '' conteúdo, mas eu não entendia como?
Curiosamente, nenhuma dessas respostas produz um regex em que a correspondência retornada é o texto dentro das aspas, o que é solicitado. MA-Madden tenta, mas apenas recebe a partida interna como um grupo capturado, e não a partida inteira. Uma maneira de fazer isso seria:
(?<=(["']\b))(?:(?=(\\?))\2.)*?(?=\1)
Exemplos para isso podem ser vistos nesta demonstração https://regex101.com/r/Hbj8aP/1
A chave aqui é o olhar positivo por trás no início (o ?<=
) e o olhar positivo no final (o ?=
). O lookbehind está olhando por trás do caractere atual para procurar uma cotação, se encontrado, em seguida, começa a partir daí e o lookahead verifica o personagem à frente para obter uma cotação e, se encontrado, interrompe esse caractere. O grupo lookbehind (the ["']
) é colocado entre colchetes para criar um grupo para a citação que foi encontrada no início, depois é usada no final da lookahead (?=\1)
para garantir que só pare quando encontrar a citação correspondente.
A única outra complicação é que, como a cabeça de impressão realmente não consome a citação final, ela será encontrada novamente pela aparência inicial, que faz com que o texto entre aspas finais e iniciais na mesma linha seja correspondido. Colocar um limite de palavras na citação de abertura ( ["']\b
) ajuda com isso, embora, idealmente, eu gostaria de ir além da aparência, mas não acho que isso seja possível. A parte que permite caracteres de escape no meio, tirei diretamente da resposta de Adam.
O padrão (["'])(?:(?=(\\?))\2.)*?\1
acima faz o trabalho, mas estou preocupado com o desempenho (não é ruim, mas poderia ser melhor). Mina abaixo é ~ 20% mais rápido.
O padrão "(.*?)"
está incompleto. Meu conselho para todos que estão lendo isso é apenas NÃO O USE !!!
Por exemplo, ele não pode capturar muitas strings (se necessário, posso fornecer um caso de teste exaustivo) como o abaixo:
$ string = 'Como você está? Estou
\'
bem, obrigado ';
O resto deles é tão "bom" quanto o acima.
Se você realmente se importa com desempenho e precisão, comece com o abaixo:
/(['"])((\\\1|.)*?)\1/gm
Nos meus testes, abrangia todas as strings que conheci, mas se você encontrar algo que não funcione, eu o atualizaria com prazer.
Gostei da solução de Eugen Mihailescu para combinar o conteúdo entre aspas, permitindo escapar das aspas. No entanto, descobri alguns problemas com o escape e criei o seguinte regex para corrigi-los:
(['"])(?:(?!\1|\\).|\\.)*\1
Ele faz o truque e ainda é bastante simples e fácil de manter.
Demonstração (com mais alguns casos de teste; fique à vontade para usá-lo e expandi-lo).
PS: Se você deseja apenas o conteúdo entre aspas na correspondência completa ( $0
) e não tem medo da penalidade de desempenho, use:
(?<=(['"])\b)(?:(?!\1|\\).|\\.)*(?=\1)
Infelizmente, sem as aspas como âncoras, tive que adicionar um limite \b
que não funcione bem com espaços e caracteres de limite que não sejam palavras após a citação inicial.
Como alternativa, modifique a versão inicial simplesmente adicionando um grupo e extraia o formulário da string$2
:
(['"])((?:(?!\1|\\).|\\.)*)\1
PPS: Se o seu foco é exclusivamente a eficiência, siga a solução de Casimir et Hippolyte ; é um bom.
-
, como nas coordenadas de longitude.
Esta versão
controla o retorno
/(["'])((?:(?!\1)[^\\]|(?:\\\\)*\\[^\\])*)\1/
MAIS RESPOSTAS! Aqui está a solução que eu usei
\"([^\"]*?icon[^\"]*?)\"
TLDR;
substitua o ícone da palavra pelo que você está procurando nas citações e pronto!
A maneira como isso funciona é a procura pela palavra-chave e não se importa com o que mais há entre as aspas. EG:
id="fb-icon"
id="icon-close"
id="large-icon-close"
o regex procura uma marca de citação "
e, em seguida, procura qualquer grupo possível de letras que não seja "
até encontrar icon
e qualquer grupo possível de letras que não "
seja, então busca um fechamento"
name="value"
com, name={"value"}
já que o regex dessa resposta retorna icon
/ value
como o segundo grupo (diferentemente da resposta aceita). Encontre : =\"([^\"]*?[^\"]*?)\"
Substitua :={"$1"}
Eu gostei da versão mais abrangente do Axeman, mas tive alguns problemas com ela (não combinava, por exemplo,
foo "string \\ string" bar
ou
foo "string1" bar "string2"
corretamente, então tentei corrigi-lo:
# 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)
apenas tente isso, funciona como um encanto !!!
\
indica pular caractere
" foo bar" "loloo"
. Eu suspeito que você significou para dispor que em uma corda crua como você fez com o regex: r'"\" foo bar\" \"loloo\""'
. Utilize os excelentes recursos de formatação do SO sempre que apropriado. Não são apenas cosméticos; literalmente, não podemos dizer o que você está tentando dizer se não os usar. E bem-vindo ao Stack Overflow !
echo 'junk "Foo Bar" not empty one "" this "but this" and this neither' | sed 's/[^\"]*\"\([^\"]*\)\"[^\"]*/>\1</g'
Isso resultará em:> Foo Bar <> <> mas isso <
Aqui eu mostrei a sequência de resultados entre> <'s para maior clareza, também usando a versão não gananciosa com este comando sed, nós jogamos fora o lixo antes e depois dos ""' s e depois substituí-lo pela parte entre "" e envolva-o com> <'s.
De Greg H. eu pude criar esse regex para atender às minhas necessidades.
Eu precisava corresponder a um valor específico qualificado por estar entre aspas. Deve ser uma correspondência completa, nenhuma correspondência parcial pode causar um acerto
por exemplo, "teste" não pode corresponder a "teste2".
reg = r"""(['"])(%s)\1"""
if re.search(reg%(needle), haystack, re.IGNORECASE):
print "winning..."
Caçador
Se você estiver tentando encontrar seqüências que possuem apenas um sufixo, como sintaxe de ponto, tente:
\"([^\"]*?[^\"]*?)\".localized
Onde .localized
está o sufixo?
Exemplo:
print("this is something I need to return".localized + "so is this".localized + "but this is not")
Ele irá capturar "this is something I need to return".localized
e "so is this".localized
mas não "but this is not"
.
Uma resposta suplementar para o subconjunto de codificadores Microsoft VBA, apenas um usa a biblioteca Microsoft VBScript Regular Expressions 5.5
e isso fornece o seguinte código
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
Para mim trabalhou este:
|([\'"])(.*?)\1|i
Eu usei em uma frase como esta:
preg_match_all('|([\'"])(.*?)\1|i', $cont, $matches);
e funcionou muito bem.
Todas as respostas acima são boas .... exceto que NÃO suportam todos os caracteres unicode! em ECMA Script (Javascript)
Se você é um usuário do Nó, convém a versão modificada da resposta aceita que suporte todos os caracteres unicode:
/(?<=((?<=[\s,.:;"']|^)["']))(?:(?=(\\?))\2.)*?(?=\1)/gmu
Tente aqui .
? The preceding token is not quantifiable