Как я могу создать регулярное выражение, которое будет извлекать текст с разделителями из строки? Например, учитывая строку вида
text ###token1### text text ###token2### text text
Мне нужно регулярное выражение, которое вытащит ###token1###. Да, мне тоже нужен разделитель. Добавив еще одну группу, я могу получить и то, и другое:
(###(.+?)###)





/###(.+?)###/
если вы хотите ###, тогда вам нужно
/(###.+?###)/
? означает не жадный, если бы у вас не было ?, то он захватил бы слишком много.
например '###token1### text text ###token2###' будет схвачен.
В моем первоначальном ответе был * вместо +. * означает 0 или больше. + означает 1 или более. * был неправильным, потому что это позволило бы найти ###### как действительную вещь.
Для игры с регулярными выражениями. Я настоятельно рекомендую http://www.weitz.de/regex-coach/ для Windows. Вы можете ввести нужную строку и свое регулярное выражение и посмотреть, что оно на самом деле делает.
Выбранный текст будет сохранен в \ 1 или $ 1 в зависимости от того, где вы используете свое регулярное выражение.
Предполагая, что вы также хотите сопоставить ### token2 ### ...
/###.+###/
Используйте () и \ x. Наивный пример, предполагающий, что текст внутри токенов всегда разделен символом #:
text (#+.+#+) text text (#+.+#+) text text
Затем содержимое () можно получить, используя \ 1 и \ 2 (\ 1 для первого набора, \ 2 для второго в выражении замены (при условии, что вы выполняете поиск / замену в редакторе). Например, выражение замены может быть таким:
token1: , token2:
В приведенном выше примере это должно дать:
token1: ###token1###, token2: ###token2###
Если вы используете библиотеку регулярных выражений в программе, вы, вероятно, вызовете функцию, чтобы получить содержимое первого и второго токенов, которые вы указали с помощью () вокруг них.
Что ж, когда вы используете такие разделители, как этот, в основном вы просто берете первый, а затем все, что не соответствует конечному разделителю, за которым следует конечный разделитель. Особое внимание следует обратить на то, что в случаях, подобных приведенному выше примеру, [^ #] не будет работать как проверка, чтобы убедиться, что конечный разделитель отсутствует, поскольку одиночный # приведет к сбою регулярного выражения (например, "### foo # bar # ##). В случае выше регулярного выражения для синтаксического анализа это будет следующее предположение, что пустые токены разрешены (если нет, измените * на +):
### ([^ #] | # [^ #] | ## [^ #]) * ###
В Perl вам действительно нужно что-то вроде этого:
$text = 'text ###token1### text text ###token2### text text';
while($text =~ m/###(.+?)###/g) {
print , "\n";
}
Что даст вам каждый токен по очереди в цикле while. (. *?) Гарантирует, что вы получите бит самый короткий между разделителями, не позволяя ему думать, что токен является 'token1 ### text text ### token2'.
Или, если вы просто хотите их сохранить, не зацикливайтесь сразу:
@tokens = $text =~ m/###(.+?)###/g;
Просто обратите внимание, что в Java это будет в группе (1) из экземпляра сопоставления после последнего вызова find ()