Я нашел 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
.
Если вы хотите использовать подвыражение несколько раз, не переписывая его, вы можете сгруппировать его, а затем вызвать его как подпрограмму . Подпрограммы могут вызываться по имени, индексу или относительной позиции.
Подпрограммы поддерживаются 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/
Если я правильно понимаю ваш вопрос, вы хотите повторно использовать некоторые шаблоны для построения более крупного шаблона?
string f = @"fc\d+/";
string e = @"\d+";
Regex regexObj = new Regex(f+e);
Кроме этого, использование обратных ссылок поможет только в том случае, если вы пытаетесь сопоставить ту же самую строку, что и раньше, где-то в вашем регулярном выражении.
, например
/\b([a-z])\w+\1\b/
Будет соответствовать только: text
, spaces
в над текстом:
Это образец текста, который не является заголовком, так как он не заканчивается двумя пробелами.
Нет такого предопределенного класса. Я думаю, вы можете упростить его с помощью опции игнорировать-case, например :
(?i)(?<from>[0-9a-z]{1,8})\s*:\s*(?<to>[0-9a-z]{1,8})
Почему бы не сделать что-то вроде этого, не совсем короче, но немного более ремонтопригодным.
String.Format("(?<from>{0})\s*:\s*(?<to>{0})", "[0-9a-zA-Z]{1,8}");
Если вы хотите больше кода для самостоятельного документирования, я бы присвоил строку с регулярным выражением числа с правильно названной константной переменной.
Чтобы повторно использовать группу имен с именем 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
.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);
, как предлагается в ответ Маттиаса .