Вложение ИЛИ в регулярных выражениях
Как мне сопоставить выражение, где мне нужно сделать or
другого набора?
то есть, как мне сопоставить что-то из формата
[
[
[ a | b ] |
[ x | y ]
]
]
где a, b, x и y - строки.
Я хочу, чтобы соответствовать фразы, как
a
b
x
y
a x
a y
b x
b y
x a
x b
y a
y b
Но не такие, как:
a b
x y
z z
Я пытаюсь использовать его в Boost Xpressive, поэтому у меня есть возможность использовать регулярные выражения типа ECMAScript или Perl.
4 ответа
Вы можете сделать это так:
[ab] [xy]|[xy] [ab]|[abxy]
Здесь есть 3 варианта:
- Только
a
,b
,x
,y
(один символ) - Или 2 символа,
a
или жеb
приходит раньшеx
или жеy
, пространство между. - Или 2 символа,
x
или жеy
приходит раньшеa
или жеb
, пространство между.
я кладу [abxy]
сзади, на всякий случай, когда вы будете искать, он будет искать тех, кто впереди (парные), прежде чем искать одиночные. Порядок важен, если вы используете регулярное выражение для поиска, но это не имеет большого значения, когда вы делаете проверку.
Еще один способ написать это:
[ab]( [xy])?|[xy]( [ab])?
Это работает только для персонажа, но вы можете сделать это работает для строки. Например, скажем, у вас есть 4 строки s1
, s2
, s3
, s4
:
(s1|s2)( (s3|s4))?|(s3|s4)( (s1|s2))?
Он ищет:
- Или
s1
или жеs2
, может или не может (0 или 1 экземпляр) с последующимs3
или жеs4
- (Наоборот)
Это охватывает все случаи s1
, s2
и т. д. (одна строка), s2 s3
, s3 s2
и т. д. (в паре, может изменить порядок). Приведенное выше регулярное выражение будет искать более длинную версию (в паре), прежде чем прибегнуть к одной строке, из-за жадного по умолчанию свойства квантификаторов.
Обратите внимание, что я использую группы захвата (pattern)
в регулярном выражении выше, которое будет записывать позицию строки, которая соответствует pattern
внутри. Вы можете сделать их без захвата группы (?:pattern)
, если вам не нужно ссылаться на текст, соответствующий шаблону. Это сэкономит вам несколько тактов.
(?:s1|s2)(?: (?:s3|s4))?|(?:s3|s4)(?: (?:s1|s2))?
(Я оставляю задачу замены группы захвата группой без захвата для другого регулярного выражения в качестве упражнения. Это так же просто, как добавление ?:
)
Поиск или проверка?
Если вы хотите найти такой шаблон, то приведенное выше регулярное выражение должно работать для вас.
Если вы хотите проверить, что строка соответствует шаблону, вам нужно использовать якоря ^
(соответствует началу строки), $
(соответствует концу строки), чтобы убедиться, что строка соответствует точному формату:
^([ab] [xy]|[xy] [ab]|[abxy])$
^([ab]( [xy])?|[xy]( [ab])?)$
^((s1|s2)( (s3|s4))?|(s3|s4)( (s1|s2))?)$
^(?:(?:s1|s2)(?: (?:s3|s4))?|(?:s3|s4)(?: (?:s1|s2))?)$
Обратите внимание, что я окружаю регулярное выражение из приведенных выше разделов ()
(захват группы, но мне здесь нужна только группировка). Это потому, что у меня есть чередование |
внутри.
Расширяемость и ограничения
Вы можете добавить больше строк в первую или вторую группу, как вам нравится:
^([abcd]( [xyz])?|[xyz]( [abcd])?)$
Однако, если вы хотите увеличить количество групп, я предлагаю разделить строку пробелами и пройтись по токенам, чтобы найти перестановки группы, а не использовать регулярное выражение.
Нет удобного способа сделать это, не повторяя a
, b
, x
а также y
в регулярном выражении, но эту проблему можно решить, построив выражение из предварительно объявленных подвыражений.
Этот код демонстрирует. Обратите внимание, что первые три строки DATA
недействительны, и они не воспроизводятся в выводе.
use v5.10;
use warnings;
my $ab = qr/a|b/;
my $xy = qr/x|y/;
my $re = qr/^
(?:
$ab (?: \s+ $xy)? | $xy (?: \s+ $ab)?
)
$/x;
while (<DATA>) {
print if /$re/;
}
__DATA__
a b
x y
z z
a
b
x
y
a x
a y
b x
b y
x a
x b
y a
y b
выход
a
b
x
y
a x
a y
b x
b y
x a
x b
y b
Попробуй это:
^((a|b)( x| y)?|(x|y)( a| b)?)$
Анатомия регулярного выражения:
# ^ - Line start
# ( - Group start
# (a|b)( x| y) - Match A or B followed by X or Y
# ? - Where (X|Y) is optional
# | - Or
# (x|y)( a| b) - Match X or Y followed by A or B
# ? - Where (A|B) is optional
# ) - And group
# $ - End of line.
Это соответствует:
a y
b a x
x y b
Но нет:
a b
x y
z z