Düzenli İfadeler: "seçeneği bölünmüş" nasıl

6 Cevap php

Bu reqular ifadeler beni çıldırtır. Ben bu biriyle şaşırıp:

test1:[[link]] test2:[[gold|silver]] test3:[[out1[[inside]]out2]] test4:this|not

Task:
Remove all [[ and ]] and if there is an option split choose the later one so output should be:

test1:link test2:silver test3:out1insideout2 test4:this|not

I (PHP) ile geldi

$text = preg_replace("/\\[\\[|\\]\\]/",'',$text); // remove [[ or ]]

Bu görevin part1 için çalışıyor. ama bundan önce ben seçeneği bölünmüş, benim en iyi çözüm yapmak gerektiğini düşünüyorum:

$text = preg_replace("/\\[\\[(.*\|)(.*?)\\]\\]/",'$2',$text);

Sonuç:

test1:silver test3:[[out1[[inside]]out2]] this|not

Ben şaşırıp. bazı ücretsiz dakika ile birisi bana yardımcı olabilir? Teşekkürler!

6 Cevap

Eğer birden çok içerik "hiyerarşiler" in içeriğini tutmak istiyorum çünkü bu normal bir ifadede yapmak mümkün değildir. Bu would bir özyinelemeli düzenli ifade kullanarak, aksi halde mümkün.

Her neyse, burada aklınıza gelebilecek en basit, en açgözlü düzenli ifadesidir. Içeriği tam gereksinimleri maçlar ise only değiştirmeniz gerekir.

Bir dize koyarak zaman tüm backslash'lar kaçmak gerekir (\ olur \\.)

\[\[((?:[^][|]+|(?!\[\[|]])[^|])++\|?)*]]

Diğerleri zaten açıklandığı gibi, birden fazla geçiş ile kullanabilirsiniz. Maçlar varken değişimi gerçekleştirme, loop tutun (sadece maç grubunu 1. tutuyor.)

Buradan diğer normal ifadeler farkı size bozmadan, içeriğinde tek parantez için izin olmasıdır:

test1:[[link]] test2:[[gold|si[lv]er]]
test3:[[out1[[in[si]de]]out2]] test4:this|not

olur

test1:[[link]] test2:si[lv]er
test3:out1in[si]deout2 test4:this|not

Bunu yapmak için en kolay yolu birden fazla geçer olacağını düşünüyorum. Gibi normal bir ifade kullanabilirsiniz:

\[\[(?:[^\[\]]*\|)?([^\[\]]+)\]\]

Bu size grubundan son seçeneği vermek seçenek dizeleri yerini alacak. Artık maçlar kadar tekrar tekrar çalıştırırsanız, ilk geçiş [[out1insideout2]] ve ikinci parantez hendek olacak [[[[içeride]] out2] out1] yerini alacak (doğru sonuç almak gerekir.

Edit 1, açıklama yolu ile,

\[\[        # Opening [[
(?:         # A non-matching group (we don't want this bit)
    [^\[\]] # Non-bracket characters
    *       # Zero or more of anything but [
    \|      # A literal '|' character representing the end of the discarded options
)?          # This group is optional: if there is only one option, it won't be present
(           # The group we're actually interested in ($1)
    [^\[\]] # All the non-bracket characters
    +       # Must be at least one
)           # End of $1
\]\]        # End of the grouping.

Edit 2: Değiştirildi ifade görmezden ']' yanı sıra '[' (o biraz daha iyi olduğu gibi çalışır).

Edit 3: senin gibi bir şey gibi iç içe parantez sayısını bilmek gerek yoktur:

$oldtext = "";
$newtext = $text;
while ($newtext != $oldtext)
{
    $oldtext = $newtext;
    $newtext = preg_replace(regexp,replace,$oldtext);
}
$text = $newtext;

Temel olarak, bu çıktı girişi ile aynı olana kadar normal ifade yerine çalışmaya devam eder.

Ben PHP bilmiyorum, bu yüzden sözdizimi hataları yukarıda muhtemelen vardır unutmayın.

Neden bir seferde hepsini yapmaya çalışın. [[]] İlk çıkarın ve sonra seçenekleri ile anlaşma, iki satır kod bunu.

Iyilik açıklık ve basitlik olacak bir şey almak için çalışırken.

Tüm parçaları var gibi görünüyor.

Neden sadece basit kalan herhangi parantezleri kaldırmak değil?

$str = 'test1:[[link]] test2:[[gold|silver]] test3:[[out1[[inside]]out2]] test4:this|not';
$str = preg_replace('/\\[\\[(?:[^|\\]]+\\|)+([^\\]]+)\\]\\]/', '$1', $str);
$str = str_replace(array('[', ']'), '', $str);

Ben büyük bir regex bu gibi şeyler yapmak için çalışıyoruz "Şimdi iki sorun var" hakkında eski şaka götürür bir zihin değilim çünkü Eh, ben, sadece regex sopa vermedi. Ancak, bu bir mermi gibi bir şey vermek:

$str = 'test1:[[link]] test2:[[gold|silver]] test3:[[out1[[inside]]out2]] test4:this|not'; $reg = '/(.*?):(.*?)( |$)/'; 
preg_match_all($reg, $str, $m);
foreach($m[2] as $pos => $match) {
  if (strpos($match, '|') !== FALSE && strpos($match, '[[') !== FALSE ) {
    $opt = explode('|', $match); $match = $opt[count($opt)-1]; 
  }
  $m[2][$pos] = str_replace(array('[', ']'),'', $match );
}

foreach($m[1] as $k=>$v) $result[$k] = $v.':'.$m[2][$k];

Bu non-kaçtı dizelerini kullanarak sadece C # kullanarak, dolayısıyla diğer dillerde ters eğik çizgi iki katına sahip olacak.

String input = "test1:[[link]] " +
               "test2:[[gold|silver]] " +
               "test3:[[out1[[inside]]out2]] " +
               "test4:this|not";

String step1 = Regex.Replace(input, @"\[\[([^|]+)\|([^\]]+)\]\]", @"[[$2]]");
String step2 = Regex.Replace(step1, @"\[\[|\]\]", String.Empty);

// Prints "test1:silver test3:out1insideout2 test4:this|not"
Console.WriteLine(step2);