Есть ли способ повторить определенное регулярное выражение, использованное ранее [duplicate]

Я нашел Gengetopt очень полезным - вы указываете параметры, которые хотите с помощью простого файла конфигурации, и генерируете пару .c / .h, которую вы просто включаете и связываете с вашим заявление. Сгенерированный код использует getopt_long, похоже, обрабатывает наиболее распространенные виды параметров командной строки, и это может сэкономить много времени.

Входной файл gengetopt может выглядеть примерно так:

version "0.1"
package "myApp"
purpose "Does something useful."

# Options
option "filename" f "Input filename" string required
option "verbose" v "Increase program verbosity" flag off
option "id" i "Data ID" int required
option "value" r "Data value" multiple(1-) int optional 

Генерация кода проста и выплевывается cmdline.h и cmdline.c:

$ gengetopt --input=myApp.cmdline --include-getopt

Сгенерированный код легко интегрируется:

#include 
#include "cmdline.h"

int main(int argc, char ** argv) {
  struct gengetopt_args_info ai;
  if (cmdline_parser(argc, argv, &ai) != 0) {
    exit(1);
  }
  printf("ai.filename_arg: %s\n", ai.filename_arg);
  printf("ai.verbose_flag: %d\n", ai.verbose_flag);
  printf("ai.id_arg: %d\n", ai.id_arg);
  int i;
  for (i = 0; i < ai.value_given; ++i) {
    printf("ai.value_arg[%d]: %d\n", i, ai.value_arg[i]);
  }
}

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

16
задан johnnyRose 6 September 2016 в 16:12
поделиться

6 ответов

Подпрограммы RegEx

Если вы хотите использовать подвыражение несколько раз, не переписывая его, вы можете сгруппировать его, а затем вызвать его как подпрограмму . Подпрограммы могут вызываться по имени, индексу или относительной позиции.

Подпрограммы поддерживаются PCRE, Perl, Ruby, PHP, Delphi, R и другими. К сожалению, .NET Framework отсутствует, но есть некоторые библиотеки PCRE для .NET, которые вы можете использовать вместо этого (например, https://github.com/ltrzesniewski/pcre-net ).

Синтаксис

Вот как работают подпрограммы: допустим, вы имеете подвыражение [abc], которое вы хотите повторять три раза подряд.

Standard RegEx Any : [abc][abc][abc]

Подпрограмма, по имени Perl: & nbsp; & nbsp; & nbsp; & nbsp; (?'name'[abc])(?&name)(?&name) PCRE: (?P<name>[abc])(?P>name)(?P>name) Ruby: & nbsp; & nbsp; (?<name>[abc])\g<name>\g<name>

Подпрограмма , с помощью индекса Perl / PCRE: ([abc])(?1)(?1) Ruby: & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; ; & nbsp; & nbsp; & nbsp; ([abc])(?-1)(?-1) PCRE: ([abc])(?-1)(?-1) Ruby: & nbsp; & nbsp; ([abc])\g<-1>\g<-1>

Подпрограмма, предопределенная Это определяет подпрограмму без ее выполнения. Perl / PCRE: (?(DEFINE)(?'name'[abc]))(?P>name)(?P>name)(?P>name)

Примеры

Соответствует допустимой строке адреса IPv4, от 0.0.0.0 до 255.255.255.255: ((?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))\.(?1)\.(?1)\.(?1)

Без подпрограмм : ((?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))\.((?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))\.((?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))\.((?:25[0-5])|(?:2[0-4][0-9])|(?:[0-1]?[0-9]?[0-9]))

И решить исходную проблему: (?<from>(?P<hexnum>[0-9a-fA-F]{1,8}))\s*:\s*(?<to>(?P>hexnum))

Подробнее

http://regular-expressions.info /subroutine.html http://regex101.com/

6
ответ дан DarcyThomas 17 August 2018 в 11:45
поделиться

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

string f = @"fc\d+/";
string e = @"\d+";
Regex regexObj = new Regex(f+e);

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

, например

/\b([a-z])\w+\1\b/

Будет соответствовать только: text, spaces в над текстом:

Это образец текста, который не является заголовком, так как он не заканчивается двумя пробелами.

3
ответ дан FailedDev 17 August 2018 в 11:45
поделиться

Нет такого предопределенного класса. Я думаю, вы можете упростить его с помощью опции игнорировать-case, например :

(?i)(?<from>[0-9a-z]{1,8})\s*:\s*(?<to>[0-9a-z]{1,8})
1
ответ дан Kirill Polishchuk 17 August 2018 в 11:45
поделиться

Почему бы не сделать что-то вроде этого, не совсем короче, но немного более ремонтопригодным.

String.Format("(?<from>{0})\s*:\s*(?<to>{0})", "[0-9a-zA-Z]{1,8}");

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

4
ответ дан Mattias Wadman 17 August 2018 в 11:45
поделиться

Чтобы повторно использовать группу имен с именем regex, используйте этот синтаксис: \ k & lt; name & gt; или \ k'name '

Итак, ответ:

(?<from>[0-9a-fA-F]{1,8})\s*:\s*\k<from>

Дополнительная информация: http://www.regular-expressions.info/named.html

-2
ответ дан shanethehat 17 August 2018 в 11:45
поделиться
  • 1
    \ k соответствует точно такой же, а не той же схеме. – cholewa1992 1 September 2015 в 14:04

.NET regex не поддерживает рекурсию шаблонов, и если вы можете использовать (?<from>(?<hex>[0-9a-fA-F]{1,8}))\s*:\s*(?<to>(\g<hex>)) в Ruby и PHP / PCRE (где hex является «технической» группой захвата, чье имя не должно встречаются в основном шаблоне), в .NET вы можете просто определить блок (-ы) как отдельные переменные, а затем использовать их для построения динамического шаблона.

Начиная с C # 6, вы можете использовать интерполированный строковый литерал, который очень похож на рекурсию подпрограммы PCRE / Onigmo, но на самом деле чище и не имеет потенциального узкого места, когда группа называется тождественно с " техническая "группа захвата:

C # demo :

using System;
using System.Text.RegularExpressions;

public class Test
{
    public static void Main()
    {
        var block = "[0-9a-fA-F]{1,8}";
        var pattern = $@"(?<from>{block})\s*:\s*(?<to>{block})";
        Console.WriteLine(Regex.IsMatch("12345678  :87654321", pattern));
    }
}

$@"..." является дословным интерполированным строковым литералом, где escape-последовательности рассматриваются как комбинации буквенного обратного слэша и символа после него. Обязательно определите литерал { с помощью {{ и } с помощью }} (например, $@"(?:{block}){{5}}", чтобы повторить block 5 раз).

Для более старых версий C # используйте string.Format:

var pattern = string.Format(@"(?<from>{0})\s*:\s*(?<to>{0})", block);

, как предлагается в ответ Маттиаса .

2
ответ дан Wiktor Stribiżew 17 August 2018 в 11:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: