2016-06-16 3 views
0
// same pattern, but different look-aheads 
// 'same' followed by 'X', 'Y', or 'Z' 
string[] patterns = new string[]{ 
    "same(?=\\s*X)", 
    "same(?=\\s*Y)", 
    "same(?=\\s*Z)" 
}; 

// replacements with respect to above patterns 
string[] replacements = new string[]{ 
    "abc", 
    "def", 
    "ghi" 
}; 

// now, I need to replace 'same' with a different 
// string depending on the character after it 
string input = "same X same Y same Z"; 
var regex = new Regex(string.Join("|", patterns)); 
regex.Replace(input, m => replacements[m.PATTERN_INDEX]); 

Есть ли что-то построенное в том, что даст мне PATTERN_INDEX в приведенном выше коде?C# Regex Индекс рисунков для нескольких шаблонов

Примечание: Я не могу использовать поиск в хэш-таблице, потому что я заменяю тот же шаблон различными строками замены в зависимости от вида.

+0

Вы имеете в виду что вам нужно заменить pattern1 Жека абв и pattern2 с Def? См. Http://ideone.com/q9ayK8 –

+0

См. Http://stackoverflow.com/questions/628556/returning-only-part-of-match-from-regular-expression Это может помочь вам здесь. –

+0

Пожалуйста, внесите мой вопрос, обновите его –

ответ

1

В моем решении я захватываю X, Y и Z в трех разных группах захвата (соответственно второй, третий и четвертый, первый - захваченные пространства).

Использование функции call callback (с именем CallBack), я ищу в каждой группе, чтобы увидеть, какой из них имеет значение и заменить соответствующим текстом (либо «abc», «def», либо «ghi»).

Ключевым элементом здесь является функция обратного вызова. Когда-нибудь, чтобы сделать очень сложную замену (например, условную замену в вашем вопросе), вам абсолютно необходимо использовать функцию обратного вызова.

Еще одна ключевая концепция заключается в том, что группа захвата возвращает пустую строку, если они ничего не могут сопоставить.

using System; 
using System.Text.RegularExpressions; 

    string input = "same X same Y same Z"; 

    var myRegex = new Regex("same(\\s*)(?:(X)|(Y)|(Z))", RegexOptions.IgnoreCase); 

    string output = myRegex.Replace(input, Callback); 

    Console.WriteLine(output); 

static string Callback(Match match) { 

    string toReturn = ""; 

    if (match.Groups[2].Value != "") { 

     toReturn = "abc"; 

    } else if (match.Groups[3].Value != "") { 

     toReturn = "def"; 

    } else if (match.Groups[4].Value != "") { 

     toReturn = "ghi"; 
    } 

    return toReturn + match.Groups[1].Value + match.Groups[2].Value + 
     match.Groups[3].Value + match.Groups[4].Value; 
} 

Вы можете проверить его здесь: http://csharppad.com/gist/5c921d27cefad32a6d353a26a6906405

я не сделал C# в течение многих лет, и это заняло у меня довольно-нибудь написать, что простой пример кода, так что не ожидайте слишком много дальнейшей помощи от меня ,

Хороший успех

EDIT: Я буду писать алгоритм в PHP, так как это язык, который я использовал наиболее в наши дни.

$test = new Test(); 

echo $test->callbackregex(
    '/same(\s*)(?:(X)|(Y)|(Z))/i', 
    array(
     2 => array('abc', '$1' ,'$2'), 
     3 => array('def', '$1' ,'$3'), 
     4 => array('ghi', '$1' ,'$4') 
    ), 
    "same X same Y same Z" 
); 

class Test 
{ 
    private $replacement = array(); 

    public function callbackregex($regex, array $replacement, $input) 
    { 
     $this->replacement = $replacement; 

     return preg_replace_callback(
      $regex, 
      array($this, "callback"), 
      $input 
     ); 
    } 

    private function callback($matches) 
    { 
     $toReturn = ""; 
     $total = count($matches); 

     //I skip 0 because it is the overall match of the regex 
     for($index = 1; $index < $total; $index++) { 

      if (!empty($matches[$index]) and isset($this->replacement[$index])) { 

       $replacementArray = $this->replacement[$index]; 

       if (is_string($replacementArray)) { 

        $replacementArray = array($replacementArray); 
       } 

       foreach ($replacementArray as $replacement) { 

        if (preg_match('/^\$\d+$/', $replacement)) { 

         $i = (int) str_replace('$', '', $replacement); 

         if (isset($matches[$i])) { 

          $toReturn .= $matches[$i]; 
         } 

        } else { 

         $toReturn .= $replacement; 
        } 

       } 

      } 
     } 

     return $toReturn; 
    } 
} 

Тест: http://sandbox.onlinephpfunctions.com/code/85a5547c7194b36c763a0f8dc7672e5785ec2044

+0

Спасибо, но пока это, вероятно, сработает, это немного сложнее, чем просто использование трех отдельных поисков регулярных выражений. – bitwise

+0

Наконец, хотя после того, как я уже несколько раз искал себя, я не думаю, что такие встроенные функции существуют, хотя это определенно возможно и даже разумно ожидать, когда вы можете передать сразу несколько шаблонов. – bitwise

+0

Если вы можете найти способ, чтобы функция обратного вызова не была статичной (они не являются не PHP), вы можете поместить свой заменяющий массив в переменную класса и получить доступ к ней внутри функции. Вместо статической замены, цикл в массиве совпадений, чтобы найти, какой индекс не пуст, и сопоставить его с тем же самым индексом в заменяющем массиве (если if существует, то в противном случае заменить пустой строкой). –

Смежные вопросы