Parantez arasında dışındaki tüm whitespaces kaldırmak için regex

5 Cevap php

Ben regex ile çözmek için umuyordum bir sorun ile güreş oldum.

Diyelim ki köşeli parantez çevrili olan içinde bir alt dizenin olasılığı ile herhangi bir alfanümerik içeren bir dize var diyelim. Bu substringler böyle dize görünür her yerde olabilir. Ayrıca dirsek-ed altdizgelerin herhangi bir sayı olabilir.

Örnekler:

  • aaa [bb b]
  • aaa [bbb] ccc [d dd]
  • [Aaa] bbb [c cc]

Sen boşlukları parantez altdize bazı olduğunu görebilirsiniz, bu iyi. Ben böyle parantez dışındaki alanlarda karşılaştığınızda Benim ana sorunu şu anda:

  • Bir aa [bb b]

Şimdi parantez içindeki boşlukları korumak ama başka yerde onları kaldırmak istiyorum.

Bu gibi dizeleri için biraz daha zor olur:

  • Bir aa [bb b]c cc[d dd]e ee[f ff]

İşte dönüş olmak isterim:

  • aaa [bb b]ccc[d dd]eee[f ff]

Ben biraz zaman şimdi vb lookarounds, olumsuz iddialar hakkında farklı Tescil eski sayfaları aracılığıyla okuma ve başım dönmeye yapıyor geçirdi.

NOT: Herkes bu ziyaret ettiğiniz için, ben iç içe parantez içeren herhangi bir çözüm arıyordu değildi. Bu durumda olsaydı ben muhtemelen aşağıda belirtilen bazı yorumlar gibi pragmatik yapardım.

5 Cevap

Bu regex hile yapmak gerekir:

[ ](?=[^\]]*?(?:\[|$))

Sadece "" ile eşleşti alanını değiştirin.

Temelde yapıyor hepsi ondan önce "[" a bu varsa bunun önünde değil, "]" kaldırmak için gidiyoruz alanı olduğundan emin yapıyor.

Bu sürece, örneğin, köşeli iç içe yok gibi çalışması gerekir:

a [b [c c] b]

Bu durumda, birinci "b" sonra alan kaldırılır ve olacak için:

aa [b [c c] b]

Bu gerçekten için regex istediğiniz bir şey gibi gelmiyor. Bu aracılığıyla okuyarak doğrudan ayrıştırmak çok kolay. Pseudo-kod:

inside_brackets = false;
for ( i = 0; i < length(str); i++) {
    if (str[i] == '[' )
        inside_brackets = true;
    else if str[i] == ']'
        inside_brackets = false;
    if ( ! inside_brackets && is_space(str[i]) )
        delete(str[i]);
}

Regex ilgili bir şey ve üzerinde tekrar edilecektir Geriye bakan bir sürü şey, dahil etmek için gidiyor, ve çok daha yavaş ve daha az anlaşılır olacak.

, Iç içe parantez için bu işi yapmak sadece, sıfırdan başlayarak açık parantez üzerinde artan ve yakın parantez azaltma, inside_brackets bir sayaç değiştirmek için.

Bunu nasıl yapılmalıdır şeye bağlıdır:

a b [ c [ d [ e ] f ] g

Bu belirsiz; olası cevaplar en az şunlardır:

  • ab[ c [ d [ e ] f ]g
  • ab[ c [ d [ e ]f]g
  • dışarı hata; parantez uyuşmuyor!

İlk iki durumda, sen İfadelerinin kullanabilirsiniz. Üçüncü durumda, bir (küçük) Çözümleyici ile çok daha iyi olurdu.

Her iki durumda da bir ya da iki, ilk [ üzerine dize bölmek. [ (yani parantez dışında belli ki) önce her şeyi şerit uzaylar. Sonraki, .*\] (durumunda 1) veya .*?\] (durum 2) aramak ve çıkış için bu üzerinde hareket. Sen giriş çıkana kadar tekrarlayın.

Bu benim için çalışıyor:

(\[.+?\])|\s

Eğer değiştirmek işlevini çağırdığınızda o zaman sadece 1 $ yerine değer geçmektedir. Fikri ilk parantez içindeki desenleri bakmak ve el değmemiş konum emin olmaktır. Ve sonra parantez dışında her alan hiçbir şey yerini alır.

Ben Regex Hero (bir. NET regex tester), ve PHP ile test unutmayın. Yani bu sizin için çalışacaktır% 100 emin değilim.

Bu ilginç bir oldu. Sonra oldukça zor görünüyordu, ilk bakışta basit geliyordu. Ve sonra nihayet geldi çözüm aslında basit. Ben çözüm herhangi bir tür bir etrafa gerek yoktu şaşırdı. Ve bir etrafa kullanan herhangi bir yöntemle daha hızlı olmalıdır.

Aşağıdaki maç olacak start-of-line bazı boşluk ve ardından start-of-dirsek değil veya bir boşluk şey takiben veya sonu braket (eşleştirmek istediğiniz herhangi bir alanda önce gelmelidir ki).

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

"tüm" yerine $1 olmayan her paranteze dizisinden mekanların ilk bloğu kaldırmak olacaktır. Sen tüm boşlukları kaldırmak için maç tekrarlamak zorunda olacak.

Örnek:

abcd efg [hij klm]nop qrst u
abcdefg [hij klm]nopqrst u
abcdefg[hij klm]nopqrstu
done