Estou tentando analisar o seguinte tipo de string:
[key:"val" key2:"val2"]
onde há chave arbitrária: pares "val" dentro. Eu quero pegar o nome da chave e o valor. Para aqueles curiosos, estou tentando analisar o formato de banco de dados do task warrior.
Aqui está a minha string de teste:
[description:"aoeu" uuid:"123sth"]
que visa destacar que qualquer coisa pode estar em uma chave ou valor além do espaço, sem espaços ao redor dos dois pontos e os valores sempre estão entre aspas duplas.
No nó, esta é minha saída:
[deuteronomy][gatlin][~]$ node
> var re = /^\[(?:(.+?):"(.+?)"\s*)+\]$/g
> re.exec('[description:"aoeu" uuid:"123sth"]');
[ '[description:"aoeu" uuid:"123sth"]',
'uuid',
'123sth',
index: 0,
input: '[description:"aoeu" uuid:"123sth"]' ]
Mas description:"aoeu"
também corresponde a esse padrão. Como posso recuperar todos os jogos?
javascript
regex
regex-group
taskwarrior
gatlin
fonte
fonte
"some string".match(/regex/g)
Respostas:
Continue chamando
re.exec(s)
em um loop para obter todas as correspondências:Experimente com este JSFiddle: https://jsfiddle.net/7yS2V/
fonte
while
vez dedo … while
?while(m = re.exec(s))
, que é um IMO antipadrão, ou precisa escreverm = re.exec(s); while (m) { ... m = re.exec(s); }
. Eu prefiro odo ... if ... while
idioma, mas outras técnicas funcionariam também.g
sinalizador definido, caso contrário, o ponteiro interno não será movido para frente. Docs .str.match(pattern)
, sepattern
tiver o sinalizador globalg
, retornará todas as correspondências como uma matriz.Por exemplo:
fonte
"All of us except @Emran:emran26, @Raju:raju13 and @Noman:noman42".match(/@(\w+):(\w+)/g)
(que voltará["@Emran:emran26", "@Raju:raju13", "@Noman:noman42"]
)/@\w/g
ounew RegExp("@\\w", "g")
Para percorrer todas as correspondências, você pode usar a
replace
função:fonte
Esta é uma solução
Isso é baseado na resposta do Lawnsea, mas mais curto.
Observe que o sinalizador `g 'deve ser definido para mover o ponteiro interno para frente através de invocações.
fonte
retorna todas as correspondências como uma matriz.
Se, por algum motivo misterioso, você precisar das informações adicionais
exec
, como alternativa às respostas anteriores, poderá fazê-lo com uma função recursiva em vez de um loop da seguinte maneira (que também parece mais interessante).conforme declarado nos comentários anteriores, é importante ter
g
no final da definição de regex para mover o ponteiro para frente em cada execução.fonte
Finalmente estamos começando a ver uma
matchAll
função interna, veja aqui a tabela de descrição e compatibilidade . Parece que, a partir de maio de 2020, Chrome, Edge, Firefox e Node.js (mais de 12 anos) são suportados, mas não o IE, Safari e Opera. Parece que foi redigido em dezembro de 2018, portanto, espere algum tempo para alcançar todos os navegadores, mas acredito que chegará lá.O built-in
matchAll
função interna é boa porque retorna uma iterável . Também retorna grupos de captura para cada partida! Então você pode fazer coisas comoTambém parece que todo objeto de correspondência usa o mesmo formato que
match()
. Portanto, cada objeto é uma matriz dos grupos de correspondência e captura, além de três propriedades adicionaisindex
,input
, egroups
. Então parece:Para mais informações
matchAll
, também há uma página de desenvolvedores do Google . Existem também polyfills / calços disponíveis.fonte
Baseado na função de Agus, mas prefiro retornar apenas os valores correspondentes:
fonte
Os iteráveis são mais agradáveis:
Uso em um loop:
Ou se você deseja uma matriz:
fonte
if (m)
if (match)
matchAll
que retorna um iterável : DSe você tem ES9
(Ou seja, se o seu sistema: Chrome, Node.js, Firefox, etc suporta EcmaScript 2019 ou posterior)
Use o novo
yourString.matchAll( /your-regex/ )
.Se você não tem ES9
Se você possui um sistema mais antigo, aqui está uma função para facilitar a cópia e colar
exemplo de uso:
saídas:
fonte
Aqui está a minha função para obter as correspondências:
fonte
Desde o ES9, agora existe uma maneira melhor e mais simples de obter todas as correspondências, juntamente com informações sobre os grupos de captura e seu índice:
Atualmente, ele é suportado no Chrome, Firefox, Opera. Dependendo de quando você ler isso, verifique este link para ver seu suporte atual.
fonte
g
elastIndex
deve ser redefinida para 0 antes da chamada dematchAll
.Usa isto...
Ele retornará uma matriz de todas as correspondências ... Isso funcionaria muito bem ... Mas lembre-se de que isso não levará em conta os grupos.
fonte
Eu recomendaria definitivamente o uso da função String.match () e a criação de um RegEx relevante para ela. Meu exemplo é com uma lista de strings, que geralmente é necessária ao verificar as entradas do usuário em busca de palavras-chave e frases.
Espero que isto ajude!
fonte
Isso realmente não vai ajudar no seu problema mais complexo, mas estou postando isso de qualquer maneira, porque é uma solução simples para pessoas que não estão fazendo uma pesquisa global como você.
Simplifiquei a expressão regular na resposta para ficar mais clara (essa não é uma solução para o seu problema exato).
Isso parece mais detalhado do que é por causa dos comentários, é assim que parece sem comentários
Observe que qualquer grupo que não corresponda será listado na matriz como
undefined
valores.Esta solução usa o operador de dispersão ES6 para purificar a matriz de valores específicos de regex. Você precisará executar seu código no Babel se desejar suporte ao IE11.
fonte
Aqui está uma solução de uma linha sem um loop while .
O pedido é preservado na lista resultante.
As desvantagens potenciais são
fonte
Meu palpite é que, se houver casos extremos, como espaços extras ou ausentes, essa expressão com menos limites também poderá ser uma opção:
Teste
Circuito RegEx
O jex.im visualiza expressões regulares:
fonte
Aqui está a minha resposta:
fonte
str
) tem o formato errado (colchetes demais). Você captura apenas a chave, não o valor. Seu código tem erro de sintaxe e não é executado (os últimos parênteses). Se você responder à pergunta "antiga" com uma resposta já aceita, adicione mais conhecimento e uma resposta melhor que a já aceita. Eu não acho que sua resposta faça isso.