Como transformar a expressão regular em não gananciosa?

227

Estou usando jQuery. Eu tenho uma string com um bloco de caracteres especiais (início e fim). Quero pegar o texto desse bloco de caracteres especiais. Eu usei um objeto de expressão regular para encontrar seqüências de caracteres. Mas como posso dizer ao jQuery para encontrar vários resultados quando tiver dois caracteres especiais ou mais?

Meu HTML:

<div id="container">
    <div id="textcontainer">
     Cuc chiến pháp lý gia [|cơ thử|nghim|] th trường [|test2|đây là test ln 2|] chng khoán [|Mỹ|day la nuoc my|] và ngân hàng đầu tư quyn lc nht Ph Wall mi ch bt đầu.
    </div>
</div>

e meu código JavaScript:

$(document).ready(function() {
  var takedata = $("#textcontainer").text();
  var test = 'abcd adddb';
  var filterdata = takedata.match(/(\[.+\])/);

  alert(filterdata); 

  //end write js 
});

Meu resultado é: [| CO Qui | Nghiem |] Thị Trường [| test2 | Djay là teste LAN 2 |] Chung khoán [| Mỹ | dia la nuoc meu |] . Mas este não é o resultado que eu quero :(. Como obter [texto] para os tempos 1 e [demo] para os tempos 2?


Acabei de fazer meu trabalho depois de pesquisar informações na internet ^^. Eu faço um código como este:

var filterdata = takedata.match(/(\[.*?\])/g);
  • meu resultado é: [| cgh thử | nghiệm |], [| test2 | lây là test lần 2 |] isso está certo !. mas eu realmente não entendo isso. Você pode me responder porque?
Rueta
fonte

Respostas:

492

Os modificadores de regex não gananciosos são como suas contrapartes gananciosas, mas com uma ?sequência imediata:

*  - zero or more
*? - zero or more (non-greedy)
+  - one or more
+? - one or more (non-greedy)
?  - zero or one
?? - zero or one (non-greedy)
Asaph
fonte
29
pode ser útil notar que, ?por si só, significa 'um ou zero' (mas é ganancioso!). Por exemplo, 'bb'.replace(/b?/, 'a') //'ab'e'bb'.replace(/c?/, 'a') //'abb'
Hashbrown
1
como c não encontrou nada lá
Muhammad Umer
1
@MuhammadUmer Eu acho que ele estava sugerindo isso porque o cnão corresponde, mas você tem o ?que é 0 or 1, então ele corresponderá 0 number of c characters, portanto, substituindo-o. Não tenho idéia de como isso funciona, porque isso não compila em nenhum mecanismo de regex que eu tentei 😢
Noctis
35

Você está certo de que a ganância é um problema:

--A--Z--A--Z--
  ^^^^^^^^^^
     A.*Z

Se você quiser combinar os dois A--Z, precisará usar A.*?Z(isso ?torna o *"relutante" ou preguiçoso).

Às vezes, existem maneiras melhores de fazer isso, por exemplo,

A[^Z]*+Z

Isso usa classe de caracteres negada e quantificador possessivo, para reduzir o retorno e é provável que seja mais eficiente.

No seu caso, a regex seria:

/(\[[^\]]++\])/

Infelizmente, o regex Javascript não suporta quantificador possessivo, então você apenas tem a ver com:

/(\[[^\]]+\])/

Veja também


Resumo rápido

*   Zero or more, greedy
*?  Zero or more, reluctant
*+  Zero or more, possessive

+   One or more, greedy
+?  One or more, reluctant
++  One or more, possessive

?   Zero or one, greedy
??  Zero or one, reluctant
?+  Zero or one, possessive

Observe que os quantificadores relutantes e possessivos também são aplicáveis ​​às {n,m}construções de repetição finita .

Exemplos em Java:

System.out.println("aAoZbAoZc".replaceAll("A.*Z", "!"));  // prints "a!c"
System.out.println("aAoZbAoZc".replaceAll("A.*?Z", "!")); // prints "a!b!c"

System.out.println("xxxxxx".replaceAll("x{3,5}", "Y"));  // prints "Yx"
System.out.println("xxxxxx".replaceAll("x{3,5}?", "Y")); // prints "YY"
poligenelubricants
fonte
Copio seu regex para o meu trabalho e o resultado é: quantificador inválido + \]) [Quebre esse erro] var filterdata = takedata.match (/ (\ [[^ \]] ++ \]) /); \ n ( firebugs + Firefox) algo errado?
Rueta 13/05/19
@Rueta: aparentemente, o sabor do Javascript não suporta possessivo. Editei minha resposta para refletir esse fato. Você pode apenas usar um em +vez de dois.
polygenelubricants
1
Embora grupos atômicos possam ser usados ​​no lugar de quantificadores possessivos, o JavaScript também não suporta os grupos atômicos. Mas existe uma terceira alternativa, veja o seguinte: instanceof.me/post/52245507631/… -you can emulate atomic grouping with LookAhead. (?>a) becomes (?=(a))\1
Roland Pihlakas
2
Esta é uma resposta Java para uma pergunta JavaScript e Java! = JavaScript. Leitores, tomem nota.
21717 Roshambo
3

Eu acredito que seria assim

takedata.match(/(\[.+\])/g);

o gno final significa global, por isso não para na primeira partida.

iangraham
fonte
sim, você está certo em / g. Acabei de fazer meu trabalho com sua resposta / g ^^. Mas quando eu faço regular /(\[.+\¯)/g, meu resultado é: [| c | th | | nghiệm |] thườ trường [| test2 | você testou o lần 2 |] ch kng khoán [| Mỹ | day la nuoc meu |] :(
Rueta