Regex: correspondendo até a primeira ocorrência de um caractere

358

Estou procurando um padrão que corresponda a tudo até a primeira ocorrência de um caractere específico, digamos ";" - um ponto e vírgula .

Eu escrevi isto:

/^(.*);/

Mas na verdade corresponde a tudo (incluindo o ponto e vírgula) até a última ocorrência de um ponto e vírgula.

Leon Fedotov
fonte
65
/^(.*?);/também deve funcionar (é chamado de não ganancioso ), mas as respostas fornecidas [^;]*são melhores.
Pascal
como você selecionaria tudo, após ponto e vírgula, e não o ponto e vírgula em si.
Muhammad Umer
veja isso funciona, \w+(?!([^]+;)|;)mas isso não acontece por quê? .+(?!([^]+;)|;)
Muhammad Umer
11
Pascal, você deveria ter escrito isso como resposta!
Sean Kendle
@ Pascal Isso é adequado como resposta! Obrigado!
NeverMind9 /

Respostas:

503

Você precisa

/[^;]*/

A classe[^;] é de personagem , corresponde a tudo, exceto um ponto e vírgula.

Para citar a página de perlremanual:

Você pode especificar uma classe de caracteres anexando uma lista de caracteres em [], que corresponderá a qualquer caractere da lista. Se o primeiro caractere após o "[" for "^", a classe corresponderá a qualquer caractere que não esteja na lista.

Isso deve funcionar na maioria dos dialetos regex.

sleske
fonte
A grande parte dessa solução é que também corresponde ao final da linha, por exemplo, no meu caso, foo=bar;baz=bax;bab=bafe ela corresponde bab=bafmesmo que não haja ;exatamente o que eu preciso. Não sei por que ele funciona embora se especificação diz partidas tudo, mas o símbolo do alvo ...
skryvets
303

Seria;

/^(.*?);/

trabalhos?

O ?operador é preguiçoso, portanto, o regex agarra o mínimo possível antes de corresponder ao ;.

RJFalconer
fonte
4
sim, mas após a extensão do bicarbonato para Tim Toady, acredito que as classes de caracteres negadas vencem, pois o quantificador preguiçoso inclui retrocesso. +1 de qualquer maneira.
Amarghosh
3
Vale a pena ler sobre o tema desempenho: blog.stevenlevithan.com/archives/greedy-lazy-performance
Glenn Slaven
38

/^[^;]*/

O [^;] diz corresponde a qualquer coisa, exceto um ponto e vírgula. Os colchetes são um operador de correspondência de conjunto, essencialmente, corresponde a qualquer caractere nesse conjunto de caracteres; ^no início, ele é uma correspondência inversa, portanto, corresponda a qualquer coisa que não esteja nesse conjunto.

Glenn Slaven
fonte
3
Esteja ciente de que o primeiro ^ nesta resposta concede ao regex um significado completamente diferente: Faz com que a expressão regular procure apenas correspondências começando no início da string. Nesse caso, isso seria eficaz se você executasse a expressão regular apenas uma vez. Se você deseja procurar várias correspondências dentro de uma única string, o primeiro ^ precisaria desaparecer.
Dan Breslau
4
Ele disse que queria combinar tudo até a primeira ocorrência de ponto-e-vírgula, então presumi que ele quis dizer isso desde o início da string.
Glenn Slaven
15

Tentar /[^;]*/

Google regex character classespara detalhes.

Dan Breslau
fonte
8

texto de amostra:

"this is a test sentence; to prove this regex; that is g;iven below"

Se, por exemplo, tivermos o texto de exemplo acima, o regex /(.*?\;)/fornecerá tudo até a primeira ocorrência de ponto e vírgula ( ;), incluindo o ponto e vírgula:"this is a test sentence;"

poncius
fonte
3
não é necessário escapar do ;char, pois não é um caráter especial de regex. O agrupamento ()também não é necessário. Você pode ir com/.*?;/
Aliaksei Kliuchnikau
11
Sim, você está certo. a escapar era mais como "melhor prevenir do que remediar"
poncius
2
Esta é a resposta que eu estava procurando. Então o ? faz a partida terminar na primeira ocorrência? Qual é o nome dessa propriedade ... (vamos chamá-la) da regex?
Parziphal
11
@Parziphal o ?personagem torna a partida preguiçosa (combinando o menor número de vezes possível). Pense nos personagens regex correspondência até o primeiro ponto e vírgula, então não ir mais longe, porque dá-se (preguiçoso;))
derekantrican
5

essa não é uma solução de regex, mas algo bastante simples para a descrição do seu problema. Basta dividir sua string e obter o primeiro item da sua matriz.

$str = "match everything until first ; blah ; blah end ";
$s = explode(";",$str,2);
print $s[0];

resultado

$ php test.php
match everything until first
ghostdog74
fonte
5

Isso foi muito útil para mim, pois estava tentando descobrir como combinar todos os caracteres em uma tag xml, incluindo atributos. Eu estava correndo para o problema "combina tudo até o fim" com:

/<simpleChoice.*>/

mas conseguiu resolver o problema com:

/<simpleChoice[^>]*>/

depois de ler este post. Obrigado a todos.

Yardboy
fonte
11
Eu descobri que é muito mais eficiente analisar (cada linguagem ou estrutura possui suas próprias classes para isso) html / xml por causa de seu formato de máquina, as expressões regulares são para linguagem natural.
Leon Fedotov
11
Agradável. Eu usei isso para corrigir documentos xml com erros de sintaxe na <!DOCTYPE>tag. Desde analisador não foi capaz de lidar com isso.
Martin Schneider
5

Isso corresponderá à primeira ocorrência apenas em cada sequência e ignorará as ocorrências subsequentes.

/^([^;]*);*/
mchid
fonte
3

"/^([^\/]*)\/$/" funcionou para mim, para obter apenas as "pastas" principais de uma matriz como:

a/   <- this
a/b/
c/   <- this
c/d/
/d/e/
f/   <- this
sPooKee
fonte
2

Realmente meio triste que ninguém tenha lhe dado a resposta correta ....

Em regex,? torna não ganancioso. Por padrão, o regex corresponderá o máximo possível (ganancioso)

Basta adicionar um? e não será ganancioso e corresponderá o mínimo possível!

Boa sorte, espero que ajude.

L1amm
fonte
3
Isso depende muito da implementação real do regex e nem toda implementação possui um modo não ganancioso.
22815
0

eu achei aquilo

/^[^,]*,/

funciona bem.

',' sendo o "delimitador" aqui.

BookerVII
fonte