Найти и заменить идентификатор регулярным выражением - PullRequest
2 голосов
/ 06 ноября 2019

Я разбираю файл, содержащий операторы построчно. Я хочу:

  1. Определить все строки, содержащие назначения.
  2. Заменить идентификаторы определенных типов (вход и выход).

Строка является назначениемесли он имеет одну из следующих двух форм:

DataType Identifier = ...
Identifier = ...

Тип данных должен быть одним из: «R», «L», «H», «X», «I». Тип данных не является обязательным. Пробелы разрешены в любой позиции вокруг DataType и Идентификатора. Пример строк, содержащих операторы:

L Input = ...
DigitalOutput = ...
  R Output= ...
H AnalogInput=...
  X Output   = ...

Ожидаемый результат после синтаксического анализа приведенных выше операторов будет:

L Deprecated = ...
DigitalOutput = ...
  R Deprecated= ...
H AnalogInput=...
  X Deprecated   = ...

Файл также содержит другие операторы, кроме присваиваний, поэтому важно идентифицировать строки с присвоениямии только заменить идентификаторы в этом случае. Я пытался использовать регулярное выражение с положительным взглядом и положительным взглядом:

public void ReplaceIdentifiers(string line)
{
  List<string> validDataTypes = new List<string>{"R", "L", "H", "X", "I"};
  List<string> identifiersToReplace = new List<string>{"Input", "Output"};
  string = ...
  Regex regEx = new Regex(MyRegEx);
  regEx.Replace(line, "Deprecated");
}

Где MyRegex находится на форме (псевдокод):

$@"(?<=...){Any of the two identifiers to replace}(?=...)"

Взгляд назад:

Start of string OR 
Zero or more spaces, Any of the valid data types, Zero or more spaces OR
Zero or more spaces

Взгляд в будущее:

Zero or more spaces, =

Мне не удалось получить правильное регулярное выражение. Как мне написать регулярное выражение?

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

Поскольку регулярное выражение .NET поддерживает Lookbehind нефиксированной длины, вы можете использовать следующий шаблон:

(?<=^\s*(?:[RLHXI]\s+)?)(?:Input|Output)(?=\s*=)

И заменить на Deprecated.

Regexдемо .

C # пример:

string input = "L Input = ...\n" +
               "DigitalOutput = ...\n" + 
               "  R Output= ...\n" + 
               "H AnalogInput=...\n" + 
               "  X Output   = ...\n" + 
               "IOutput = ...\n" + 
               "Output = ...";

Regex regEx = new Regex(@"(?<=^\s*(?:[RLHXI]\s+)?)(?:Input|Output)(?=\s*=)", 
                        RegexOptions.Multiline);
string output = regEx.Replace(input, "Deprecated");
Console.WriteLine(output);

Выход:

L Deprecated = ...
DigitalOutput = ...
  R Deprecated= ...
H AnalogInput=...
  X Deprecated   = ...
IOutput = ...
Deprecated = ...

Попробуйте онлайн .

1 голос
/ 06 ноября 2019

Для показанного конкретного случая ваше регулярное выражение может быть:

^(\s*[RLHXI]\s+)(?:Output|Input)(\s*=)

заменить на $1Deprecated$2 с многострочным параметром.

Если имена типов и идентификаторы для замены не являютсядоступны во время компиляции, вы можете использовать string.format в следующем формате:

^(\s*(?:{0})\s+)(?:{1})(\s*=)

Передаваемые ему аргументы будут списками строк, соединенными с |, с использованием string.Join:

string regex = string.Format(
    @"^(\s*(?:{0})\s+)(?:{1})(\s*=)",
    string.Join("|", validDataTypes), // you should probably escape these beforehand
    string.Join("|", identifiersToReplace)
    );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...