скажем, у меня очень длинная строка. строка имеет регулярные выражения в случайных местах. Можно ли использовать регулярное выражение для поиска регулярных выражений?Мы используем регулярное выражение для выражения выражений регулярных выражений?
ответ
(Предполагая, что вы ищете регулярное выражение JavaScript буквального, ограниченное /
.)
Было бы достаточно просто просто посмотреть на все между /
, но это не всегда может быть регулярным выражением. Например, такой поиск возвращает /2 + 3/
строки var myNumber = 1/2 + 3/4
.Это означает, что вам нужно будет знать, что происходит перед регулярным выражением. Регулярному выражению должно предшествовать нечто иное, чем переменная или число. Это случаи, что я могу думать:
/regex/;
var myVar = /regex/;
myFunction(/regex/,/regex/);
return /regex/;
typeof /regex/;
case /regex/;
throw /regex/;
void /regex/;
"global" in /regex/;
В некоторых языках вы можете использовать с просмотром назад, который может выглядеть следующим образом (непроверенные!):
(?=<^|\n|[^\s\w\/]|\breturn|\btypeof|\bcase|\bthrow|\bvoid|\bin)\s*\/(?:\\\/|[^\/\*\n])(?:\\\/|[^\/\n])*\/
Однако, JavaScript не поддерживает это. Я бы рекомендовал имитировать lookbehind, поставив часть регулярного выражения, предназначенную для соответствия самому литералу в группе захвата и доступа к ней. Все случаи, которые я отдаю себе отчет может соответствовать этому регулярному выражению:
(?:^|\n|[^\s\w\/]|\breturn|\btypeof|\bcase|\bthrow|\bvoid|\bin)\s*(\/(?:\\\/|[^\/\*\n])(?:\\\/|[^\/\n])*\/)
ПРИМЕЧАНИЕ: Это регулярное выражение иногда приводит к ложным срабатываниям в комментариях.
Если вы хотите, чтобы также захватить модификаторы (например /regex/gim
), используйте
(?:^|\n|[^\s\w\/]|\breturn|\btypeof|\bcase|\bthrow|\bvoid|\bin)\s*(\/(?:\\\/|[^\/\*\n])(?:\\\/|[^\/\n])*\/\w*)
Если есть зарезервированные слова, я пропускаю, что может сопровождаться регулярным выражением буквального, просто добавьте в конце первая группа: |\b
ключевого слова
Все, что остается тогда, чтобы получить доступ к группе захвата, используя код похож на следующее:
var codeString = "function(){typeof /regex/;}";
var searchValue = /(?:^|\n|[^\s\w\/]|\breturn|\btypeof|\bcase|\bthrow)\s*(\/(?:\\\/|[^\/\*\n])(?:\\\/|[^\/\n])*\/)/g;
// the global modifier is necessary!
var match = searchValue.exec(codeString); // "['typeof /regex/','/regex/']"
match = match[1]; // "/regex/"
UPDATE
Я просто исправили ошибку с регулярным выражением в отношении сбежавших слэш, что повлекло бы за это получить только /\/
из регулярного выражения, как /\/hello/
UPDATE 4/6
Добавлена поддержка для void
и in
. Вы не можете слишком винить меня за то, что не включаете это сначала, так как даже Stack Overflow не делает этого, если вы посмотрите на синтаксическую раскраску в первом блоке кода.
Это не лучший способ для этого.
Вы можете сделать это с некоторой степенью уверенности (используя EOL, чтобы разбить на подстроки и найти те, которые выглядят как регулярные выражения, возможно ограниченные кавычками), однако не забывайте, что очень длинная строка CAN может быть регулярным выражением , поэтому у вас никогда не будет полной уверенности в использовании этого подхода.
Что вы подразумеваете под "регулярным выражением"? aaaa
- действительное регулярное выражение. This is also a regular expression
. Если вы имеете в виду литерал регулярных выражений, вам может понадобиться примерно следующее: /\/(?:[^\\\/]|\\.)*\//
(адаптировано от here).
UPDATE
slebetman делает хорошую точку; Литералам регулярных выражений не нужно начинать с /
. В Perl или sed они могут начинаться с того, что вы хотите. По существу, то, что вы пытаетесь сделать, является рискованным и, вероятно, не будет работать для всех случаев.
Реляционный литерал зависит только от языка программирования. В tcl литерал регулярного выражения делится на {}. В C это «". И в Perl его можно разделить на все, что вы выберете. – slebetman
@siebetman Хорошая точка. Я подумал об этом, но забыл упомянуть об этом. Будет обновляться. –
Да, если вы знаете, будет ли (и как!) Ваше регулярное выражение ограничено. Скажем, например, что ваша строка является чем-то вроде
aaaaa...aaa/b/aaaaa
где «Ь» является «регулярное выражение» разграничены по характеру /
(это почти базовый сценарий); вам нужно сканировать строку для ожидаемого разделителя, извлечь все, что находится внутри разделителей (обращая внимание на escape-символы), и вы должны быть установлены.
Это если ваш разделителем является известный персонаж и если вы уверены, что он появляется четное число раз, или вы хотите отказаться от остальных (например, какой набор разделителей вы рассматриваете в следующая строка: aaa/b/aaa/c/aaa/d
)
Если это так, то вам нужно следовать тем же соображениям, что и вы, чтобы найти подстроку в заданной строке. Когда вы найдете первое регулярное выражение, продолжайте разбор, пока не нажмете конец строки или не найдете другое регулярное выражение и так далее.
Я подозреваю, что вы ищете «общее правило» для поиска любой строки, которая после разбора приведет к действительному регулярному выражению (скажем, мы говорим о POSIX regexp - попробуйте man re_format
, если вы под BSD). Если это так, вы можете попробовать каждую возможную подстроку каждой длины данной строки и передать ее парсеру regexp для корректности синтаксиса. Тем не менее, вы ничего не доказали с точки зрения правильности регулярного выражения, то есть на то, что действительно совпадают.
Если это то, что вы пытаетесь сделать, я настоятельно рекомендую найти другой способ или объяснить, что вы пытаетесь сделать здесь.
В чем разница между частью без регулярного выражения строки и частью регулярного выражения? – jball
Конечно, но если вы собираетесь охватить весь синтаксис регулярных выражений, вы просто создали себе предварительный парсер. Я бы предложил предоставить больше спецификации для вопросов. –
@ jball, ничего, они случайные персонажи –