Поделиться через


Подстановки в регулярных выражениях

Замены — это элементы языка, распознаваемые только в шаблонах замены. Они используют шаблон регулярного выражения для определения всего или части текста, заменяющего соответствующий текст во входной строке. Шаблон замены может состоять из одного или нескольких подстановок вместе с буквальными символами. Шаблоны замены предоставляются для перегрузок метода Regex.Replace с параметром replacement, а также для метода Match.Result. Методы заменяют сопоставленный шаблон на шаблон, определяемый параметром replacement.

.NET определяет элементы подстановки, перечисленные в следующей таблице.

Замещение Описание
$ число Включает последнюю подстроку, соответствующую захватывающей группе, которую определяет число, где число является десятичным значением, в строке замены. Дополнительные сведения см. в разделе "Подстановка нумерованной группы".
${ name } Включает последнюю подстроку, соответствующую именованной группе, обозначенной в строке замены (?<именем> ). Дополнительные сведения см. в разделе «Подстановка именованной группы».
$$ Включает один литерал "$" в строку замены. Дополнительные сведения см. в разделе Замена символа "$".
$& Включает копию всего совпадения в строку замены. Дополнительные сведения см. в разделе "Подстановка всего совпадения".
$` Включает весь текст входной строки до совпадения в строке замены. Дополнительные сведения см. в разделе Подстановки текста перед сопоставлением.
$' Включает весь текст входной строки, который следует после совпадения, в строку замены. Дополнительные сведения см. в разделе "Подстановка текста" после сопоставления.
$+ Включает последнюю группу, записанную в строке замены. Дополнительные сведения см. в разделе «Подстановка последней захваченной группы».
$_ Включает всю входную строку в строке замены. Дополнительные сведения см. в разделе "Подстановка всей входной строки".

Элементы подстановки и шаблоны замены

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

Единственным символом, который может отображаться в шаблоне регулярного выражения или в подстановке, является $ символ, хотя он имеет другое значение в каждом контексте. В шаблоне регулярного выражения $ — это привязка, которая соответствует концу строки. В образце замены $ указывает начало подстановки.

Замечание

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

Замена нумерованной группы

Элемент $ языка чисел включает последнюю подстроку, соответствующую группе записи чисел в строке замены, где число является индексом группы записи. Например, шаблон $1 замены указывает, что соответствующая подстрока должна быть заменена первой захваченной группой. Дополнительные сведения о нумерованных захватывающих группах см. в разделе Конструкции группирования.

Все следующие $ цифры интерпретируются как принадлежащие группе чисел . Если это не ваше намерение, вместо этого можно заменить именованную группу. Например, можно использовать строку замены ${1}1 вместо $11, чтобы определить её как значение первой захваченной группы, добавив число "1". Дополнительные сведения см. в разделе «Подстановка именованной группы».

Захватываемые группы, которым явно не присваиваются имена с помощью синтаксиса (?<name>), нумеруются слева направо, начиная с единицы. Именованные группы также нумеруются слева направо, начиная с на единицу больше индекса последней неименованной группы. Например, в регулярном выражении (\w)(?<digit>\d)индекс digit именованной группы равен 2.

Если число не указывает допустимую группу захвата, определенную в шаблоне регулярного выражения, $число интерпретируется как буквальная последовательность символов, которая используется для замены каждого совпадения.

В следующем примере используется $ замена числа для удаления денежного символа из десятичного значения. Он удаляет символы валюты, найденные в начале или конце денежной стоимости, и распознает два наиболее распространенных разделителя десятичных знаков ("." и ",").

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\p{Sc}*(\s?\d+[.,]?\d*)\p{Sc}*";
      string replacement = "$1";
      string input = "$16.32 12.19 £16.29 €18.29  €18,29";
      string result = Regex.Replace(input, pattern, replacement);
      Console.WriteLine(result);
   }
}
// The example displays the following output:
//       16.32 12.19 16.29 18.29  18,29
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\p{Sc}*(\s?\d+[.,]?\d*)\p{Sc}*"
        Dim replacement As String = "$1"
        Dim input As String = "$16.32 12.19 £16.29 €18.29  €18,29"
        Dim result As String = Regex.Replace(input, pattern, replacement)
        Console.WriteLine(result)
    End Sub
End Module
' The example displays the following output:
'       16.32 12.19 16.29 18.29  18,29

Шаблон регулярного выражения \p{Sc}*(\s?\d+[.,]?\d*)\p{Sc}* определяется, как показано в следующей таблице.

Рисунок Описание
\p{Sc}* Соответствует нулю или нескольким символам символов валюты.
\s? Совпадение с нулем или одним символом пробела.
\d+ Совпадает с одной или несколькими десятичными цифрами.
[.,]? Соответствует нулю или одной точке или запятой.
\d* Соответствует нулю или нескольким десятичным числам.
(\s?\d+[.,]?\d*) Соответствует пробелу, за которым следует одна или несколько десятичных цифр, затем ноль или одна точка или запятая, затем ноль или несколько десятичных цифр. Это первая группа захвата. Так как шаблон замены является $1, вызов Regex.Replace метода заменяет всю соответствующую подстроку этой захваченной группой.

Замена именованной группы

Элемент ${ языка имя} заменяет последнюю подстроку, соответствующую группе захвата имя, где имя является именем группы захвата, определенной элементом языка (?<имя>). Дополнительные сведения о именованных группах записи см. в разделе "Конструкции группирования".

Если имя не указывает допустимую группу записи имен, определенную в шаблоне регулярного выражения, но состоит из цифр, ${имя} интерпретируется как нумерованной группой.

Если имя не указывает ни действительную именованную группу захвата, ни действительную нумерованную группу захвата, определённую в шаблоне регулярных выражений, ${имя} интерпретируется как литеральная последовательность символов, которая используется для замены каждого совпадения.

В следующем примере используется подстановка ${} для удаления символа валюты из десятичного числа. Он удаляет символы валюты, найденные в начале или конце денежной стоимости, и распознает два наиболее распространенных разделителя десятичных знаков ("." и ",").

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\p{Sc}*(?<amount>\s?\d+[.,]?\d*)\p{Sc}*";
      string replacement = "${amount}";
      string input = "$16.32 12.19 £16.29 €18.29  €18,29";
      string result = Regex.Replace(input, pattern, replacement);
      Console.WriteLine(result);
   }
}
// The example displays the following output:
//       16.32 12.19 16.29 18.29  18,29
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\p{Sc}*(?<amount>\s?\d+[.,]?\d*)\p{Sc}*"
        Dim replacement As String = "${amount}"
        Dim input As String = "$16.32 12.19 £16.29 €18.29  €18,29"
        Dim result As String = Regex.Replace(input, pattern, replacement)
        Console.WriteLine(result)
    End Sub
End Module
' The example displays the following output:
'       16.32 12.19 16.29 18.29  18,29

Шаблон регулярного выражения \p{Sc}*(?<amount>\s?\d[.,]?\d*)\p{Sc}* определяется, как показано в следующей таблице.

Рисунок Описание
\p{Sc}* Соответствует нулю или нескольким символам символов валюты.
\s? Совпадение с нулем или одним символом пробела.
\d+ Совпадает с одной или несколькими десятичными цифрами.
[.,]? Соответствует нулю или одной точке или запятой.
\d* Соответствует нулю или нескольким десятичным числам.
(?<amount>\s?\d[.,]?\d*) Соответствует пробелу, за которым следуют одна или несколько десятичных цифр, затем ноль или одна точка либо запятая, а далее ноль или более десятичных цифр. Это группа записи с именем amount. Так как шаблон замены является ${amount}, вызов Regex.Replace метода заменяет всю соответствующую подстроку этой захваченной группой.

Замена символа "$"

Подстановка $$ вставляет литеральный символ "$" в замененную строку.

В следующем примере используется объект NumberFormatInfo для определения символа валюты текущей культуры и его расположения в строке валюты. Затем он создает шаблон регулярного выражения и шаблон замены динамически. Если пример выполняется на компьютере, где текущие языковые и региональные параметры заданы как en-US, то он формирует регулярное выражение по шаблону \b(\d+)(\.(\d+))? и шаблон замены $$ $1$2. Шаблон замены заменяет соответствующий текст символом валюты и пробелом, за которым следует первая и вторая захваченные группы.

using System;
using System.Globalization;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      // Define array of decimal values.
      string[] values= { "16.35", "19.72", "1234", "0.99"};
      // Determine whether currency precedes (True) or follows (False) number.
      bool precedes = NumberFormatInfo.CurrentInfo.CurrencyPositivePattern % 2 == 0;
      // Get decimal separator.
      string cSeparator = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
      // Get currency symbol.
      string symbol = NumberFormatInfo.CurrentInfo.CurrencySymbol;
      // If symbol is a "$", add an extra "$".
      if (symbol == "$") symbol = "$$";

      // Define regular expression pattern and replacement string.
      string pattern = @"\b(\d+)(" + cSeparator + @"(\d+))?";
      string replacement = "$1$2";
      replacement = precedes ? symbol + " " + replacement : replacement + " " + symbol;
      foreach (string value in values)
         Console.WriteLine($"{value} --> {Regex.Replace(value, pattern, replacement)}");
   }
}
// The example displays the following output:
//       16.35 --> $ 16.35
//       19.72 --> $ 19.72
//       1234 --> $ 1234
//       0.99 --> $ 0.99
Imports System.Globalization
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        ' Define array of decimal values.
        Dim values() As String = {"16.35", "19.72", "1234", "0.99"}
        ' Determine whether currency precedes (True) or follows (False) number.
        Dim precedes As Boolean = (NumberFormatInfo.CurrentInfo.CurrencyPositivePattern Mod 2 = 0)
        ' Get decimal separator.
        Dim cSeparator As String = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator
        ' Get currency symbol.
        Dim symbol As String = NumberFormatInfo.CurrentInfo.CurrencySymbol
        ' If symbol is a "$", add an extra "$".
        If symbol = "$" Then symbol = "$$"

        ' Define regular expression pattern and replacement string.
        Dim pattern As String = "\b(\d+)(" + cSeparator + "(\d+))?"
        Dim replacement As String = "$1$2"
        replacement = If(precedes, symbol + " " + replacement, replacement + " " + symbol)
        For Each value In values
            Console.WriteLine("{0} --> {1}", value, Regex.Replace(value, pattern, replacement))
        Next
    End Sub
End Module
' The example displays the following output:
'       16.35 --> $ 16.35
'       19.72 --> $ 19.72
'       1234 --> $ 1234
'       0.99 --> $ 0.99

Шаблон регулярного выражения \b(\d+)(\.(\d+))? определяется, как показано в следующей таблице.

Рисунок Описание
\b Начните поиск совпадений на границе слова.
(\d+) Совпадает с одной или несколькими десятичными цифрами. Это первая группа захвата.
\. Соответствует периоду (десятичному разделитетелю).
(\d+) Совпадает с одной или несколькими десятичными цифрами. Это третья группа захвата.
(\.(\d+))? Соответствует нулю или одному вхождения периода, за которым следует одна или несколько десятичных цифр. Это вторая группа захвата.

Замена полного совпадения

Подстановка $& включает весь матч в строке замены. Часто она используется для добавления подстроки в начало или конец соответствующей строки. Например, шаблон замены ($&) добавляет скобки в начале и конце каждого совпадения. Если совпадения $& нет, замена не имеет эффекта.

В следующем примере используется подстановка $& для добавления кавычек в начале и конце названий книг, хранящихся в строковом массиве.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"^(\w+\s?)+$";
      string[] titles = { "A Tale of Two Cities",
                          "The Hound of the Baskervilles",
                          "The Protestant Ethic and the Spirit of Capitalism",
                          "The Origin of Species" };
      string replacement = "\"$&\"";
      foreach (string title in titles)
         Console.WriteLine(Regex.Replace(title, pattern, replacement));
   }
}
// The example displays the following output:
//       "A Tale of Two Cities"
//       "The Hound of the Baskervilles"
//       "The Protestant Ethic and the Spirit of Capitalism"
//       "The Origin of Species"
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "^(\w+\s?)+$"
        Dim titles() As String = {"A Tale of Two Cities", _
                                   "The Hound of the Baskervilles", _
                                   "The Protestant Ethic and the Spirit of Capitalism", _
                                   "The Origin of Species"}
        Dim replacement As String = """$&"""
        For Each title As String In titles
            Console.WriteLine(Regex.Replace(title, pattern, replacement))
        Next
    End Sub
End Module
' The example displays the following output:
'       "A Tale of Two Cities"
'       "The Hound of the Baskervilles"
'       "The Protestant Ethic and the Spirit of Capitalism"
'       "The Origin of Species"

Шаблон регулярного выражения ^(\w+\s?)+$ определяется, как показано в следующей таблице.

Рисунок Описание
^ Начать поиск совпадения в начале входной строки.
(\w+\s?)+ Соответствие шаблону, включающего один или несколько буквенных символов, за которыми следуют ноль или один символ пробела, происходит один или несколько раз.
$ Соответствует концу входной строки.

Шаблон "$&" замены добавляет буквальную кавычку в начале и в конце каждого совпадения.

Замена текста перед совпадением

Подстановка $` заменяет совпадающую строку всей входной строкой, которая предшествует совпадению. То есть он дублирует исходную строку до совпадения, удаляя совпадающий текст. Любой текст, следующий за соответствующим текстом, не изменяется в результирующей строке. Если в входной строке имеется несколько совпадений, замещающий текст является производным от исходной входной строки, а не из строки, в которой текст был заменен предыдущими совпадениями. (Пример является иллюстрацией.) Если совпадения $` нет, то замена не действует.

В следующем примере шаблон \d+ регулярного выражения используется для сопоставления последовательности одной или нескольких десятичных цифр в входной строке. Строка замены $` заменяет эти цифры текстом, который предшествует совпадению.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "aa1bb2cc3dd4ee5";
      string pattern = @"\d+";
      string substitution = "$`";
      Console.WriteLine("Matches:");
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine($"   {match.Value} at position {match.Index}");

      Console.WriteLine($"Input string:  {input}");
      Console.WriteLine("Output string: " +
                        Regex.Replace(input, pattern, substitution));
   }
}
// The example displays the following output:
//    Matches:
//       1 at position 2
//       2 at position 5
//       3 at position 8
//       4 at position 11
//       5 at position 14
//    Input string:  aa1bb2cc3dd4ee5
//    Output string: aaaabbaa1bbccaa1bb2ccddaa1bb2cc3ddeeaa1bb2cc3dd4ee
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim input As String = "aa1bb2cc3dd4ee5"
        Dim pattern As String = "\d+"
        Dim substitution As String = "$`"
        Console.WriteLine("Matches:")
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
        Next
        Console.WriteLine("Input string:  {0}", input)
        Console.WriteLine("Output string: " + _
                          Regex.Replace(input, pattern, substitution))
    End Sub
End Module
' The example displays the following output:
'    Matches:
'       1 at position 2
'       2 at position 5
'       3 at position 8
'       4 at position 11
'       5 at position 14
'    Input string:  aa1bb2cc3dd4ee5
'    Output string: aaaabbaa1bbccaa1bb2ccddaa1bb2cc3ddeeaa1bb2cc3dd4ee

В этом примере входная строка "aa1bb2cc3dd4ee5" содержит пять совпадений. В следующей таблице показано, как подстановка $` заставляет движок регулярных выражений заменять каждое совпадение во входной строке. Вставленный текст отображается полужирным шрифтом в столбце результатов.

Матч Позиция Строка перед совпадением Строка результата
1 2 Аа aaaabb2cc3dd4ee5
2 5 aa1bb aaaabb aa1bbcc3dd4ee5
3 8 aa1bb2cc aaaabbaa1bbcc aa1bb2ccdd4ee5
4 11 aa1bb2cc3dd aaaabbaa1bbccaa1bb2cc2ccddaa1bb2cc3ddee5
5 14 aa1bb2cc3dd4ee aaaabbaa1bbccaa1bb2ccdaa1bb2cc3deeaa1bb2cc3dd4ee

Замена текста после совпадения

Подстановка $' заменяет соответствующую строку всей входной строкой после совпадения. То есть, он дублирует входную строку после совпадения, удаляя при этом совпавший текст. Любой текст, предшествующий сопоставленному тексту, не изменяется в результирующей строке. Если совпадения $' нет, замена не имеет эффекта.

В следующем примере шаблон \d+ регулярного выражения используется для сопоставления последовательности одной или нескольких десятичных цифр в входной строке. Строка $' заменяет эти цифры текстом, который следует за совпадением.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "aa1bb2cc3dd4ee5";
      string pattern = @"\d+";
      string substitution = "$'";
      Console.WriteLine("Matches:");
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine($"   {match.Value} at position {match.Index}");
      Console.WriteLine($"Input string:  {input}");
      Console.WriteLine("Output string: " +
                        Regex.Replace(input, pattern, substitution));
   }
}
// The example displays the following output:
//    Matches:
//       1 at position 2
//       2 at position 5
//       3 at position 8
//       4 at position 11
//       5 at position 14
//    Input string:  aa1bb2cc3dd4ee5
//    Output string: aabb2cc3dd4ee5bbcc3dd4ee5ccdd4ee5ddee5ee
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim input As String = "aa1bb2cc3dd4ee5"
        Dim pattern As String = "\d+"
        Dim substitution As String = "$'"
        Console.WriteLine("Matches:")
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
        Next
        Console.WriteLine("Input string:  {0}", input)
        Console.WriteLine("Output string: " + _
                          Regex.Replace(input, pattern, substitution))
    End Sub
End Module
' The example displays the following output:
'    Matches:
'       1 at position 2
'       2 at position 5
'       3 at position 8
'       4 at position 11
'       5 at position 14
'    Input string:  aa1bb2cc3dd4ee5
'    Output string: aabb2cc3dd4ee5bbcc3dd4ee5ccdd4ee5ddee5ee

В этом примере входная строка "aa1bb2cc3dd4ee5" содержит пять совпадений. В следующей таблице показано, как подстановка $' заставляет движок регулярных выражений заменять каждое совпадение во входной строке. Вставленный текст отображается полужирным шрифтом в столбце результатов.

Матч Позиция Строка после совпадения Строка результата
1 2 bb2cc3dd4ee5 aabb2cc3dd4ee5bb2cc3dd4ee5
2 5 cc3dd4ee5 aabb2cc3dd4ee5bbcc3dd4ee5 cc3dd4ee5
3 8 dd4ee5 aabb2cc3dd4ee5bbcc3dd4ee5ccdd4ee5dd4ee5
4 11 ee5 aabb2cc3dd4ee5bbcc3dd4ee5ccdd4ee5dee5 ee5
5 14 String.Empty aabb2cc3dd4ee5bbcc3dd4ee5ccd4ee5dee

Замена последней сохраненной группы

Подстановка $+ заменяет соответствующую строку последней захваченной группой. Если нет захваченных групп или если значение последней захваченной группы String.Empty отсутствует, подстановка $+ не действует.

Следующий пример определяет повторяющиеся слова в строке и использует $+ подстановку для их замены одним вхождением слова. Этот RegexOptions.IgnoreCase параметр используется для обеспечения того, чтобы слова, отличающиеся в случае, но которые в противном случае идентичны, считаются дубликатами.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\w+)\s\1\b";
      string substitution = "$+";
      string input = "The the dog jumped over the fence fence.";
      Console.WriteLine(Regex.Replace(input, pattern, substitution,
                        RegexOptions.IgnoreCase));
   }
}
// The example displays the following output:
//      The dog jumped over the fence.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(\w+)\s\1\b"
        Dim substitution As String = "$+"
        Dim input As String = "The the dog jumped over the fence fence."
        Console.WriteLine(Regex.Replace(input, pattern, substitution, _
                                        RegexOptions.IgnoreCase))
    End Sub
End Module
' The example displays the following output:
'      The dog jumped over the fence.

Шаблон регулярного выражения \b(\w+)\s\1\b определяется, как показано в следующей таблице.

Рисунок Описание
\b Начинайте сопоставление на границе слова.
(\w+) Найти один или несколько символов слова. Это первая группа захвата.
\s Соответствует символу пробела.
\1 Соответствует первой захваченной группе.
\b Совпадение должно заканчиваться на границе слова.

Замена всей входной строки

Подстановка $_ заменяет соответствующую строку всей входной строкой. То есть, он удаляет совпадающий текст и заменяет его всей строкой, включая исходный совпадающий текст.

Следующий пример находит одну или несколько десятичных цифр во входной строке. Он использует подстановку $_ , чтобы заменить их всей входной строкой.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "ABC123DEF456";
      string pattern = @"\d+";
      string substitution = "$_";
      Console.WriteLine($"Original string:          {input}");
      Console.WriteLine($"String with substitution: {Regex.Replace(input, pattern, substitution)}");
   }
}
// The example displays the following output:
//       Original string:          ABC123DEF456
//       String with substitution: ABCABC123DEF456DEFABC123DEF456
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim input As String = "ABC123DEF456"
        Dim pattern As String = "\d+"
        Dim substitution As String = "$_"
        Console.WriteLine("Original string:          {0}", input)
        Console.WriteLine("String with substitution: {0}", _
                          Regex.Replace(input, pattern, substitution))
    End Sub
End Module
' The example displays the following output:
'       Original string:          ABC123DEF456
'       String with substitution: ABCABC123DEF456DEFABC123DEF456

В этом примере входная строка "ABC123DEF456" содержит два совпадения. В следующей таблице показано, как подстановка $_ заставляет движок регулярных выражений заменять каждое совпадение во входной строке. Вставленный текст отображается полужирным шрифтом в столбце результатов.

Матч Позиция Матч Строка результата
1 3 123 ABCABC123DEF456DEF456
2 5 456 ABCABC123DEF456DEF ABC123DEF456

См. также