2015-05-04 4 views
1

Не может показаться, что это получается - я пытаюсь найти регулярное выражение, которое будет соответствовать строке, если оно содержит «*» в ЛЮБОЙ позиции, но НЕ, если звездочке предшествует обратная косая черта. Например:JavaScript RegEx для соответствия «*», если только предшествует обратная косая черта

abcd: false 
*abcd: true 
abcde*fghi*: true 
abc\*defg: false 
\*abcdefg: false 

Я думал, что я на правильном пути с этим, но он не работает:

/[^\\]\*/ 

Спасибо!

ответ

8

Это не так просто, как кажется.

Что делать, если обратные косые черты обратно сбрасываются?

\\* should be true, while 
    \* this should be false 

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

/(?:^|[^\\])((\\\\)*\*)/.test(string); 
/* returns true for unescaped asterisks */ 

Примеры:

abcd false 
*abcd true 
\*abcd false 
\\*abcd true 
\\\*abcd false 
\\\\*abcd true 
+1

Хорошо. – nderscore

+0

Эй, может, ты поможешь мне связать вопрос? Мне интересно, как я могу разбить строку на символ (например, звездочка, на самом деле не имеет значения), за исключением случаев, когда этот символ был сбрасыван нечетным числом раз. Я попытался поместить ваше регулярное выражение в 'String.split()', но он не сделал то, что я хотел, и не могу понять, как это сделать. Вы знаете, как это сделать? – Evert

+0

Ничего, я понял это. Я хотел разбить символ '|', вот мой код: '' a | b \\ | c \\\\ | d ".replace (/ (^ | [^ \\]) (? :(\\\\) * \ |)/g, "$ 1 $ 2 \ x00"). split ("\ x00"); ' – Evert

1

Ваше регулярное выражение должно работать. Фактически, здесь он (работает) на regex101.

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

+1

'/^\ * | [^ \\] \ * /' работает (добавлено '^ \ * |' в начало). – Pluto

+0

@nderscore: да, это то, что я объяснил в отказе от ответственности - что звездочка не может быть первым персонажем. Вы предоставили полное решение, поэтому я поддержал его. –

1

К сожалению, JavaScript не поддерживает просмотр назад, но вот регулярное выражение, которое должно работать:

/(?:^|[^\\])\*/

Объяснение:

(?:^|[^\\]) - без захвата группы, чтобы захватить либо начало строки или символ, отличный от \.

\* - следующая звездочка.

Вот демо с примерами:

var unescapedAsterisk = /(?:^|[^\\])\*/; 

['abcd', '*abcd', 'abcde*fghi*', 'abc\\*defg', '\\*abcdefg'].forEach(function(str){ 
    console.log(str, unescapedAsterisk.test(str)); 
}); 
3

Хотя в этом случае простой /(^|[^\\])\*/ должен сделать трюк, мне нравится держать вещи проще.

var matches = line.indexOf("*") >= 0 && line.indexOf("\\*") < 0; 

В буквальном смысле: Если строка содержит * и не содержит \*, то вы хорошо!

+0

Вопрос гласит, что '\ *' в порядке, пока звездочка не будет продолжена обратным слэшем где-то в другом месте. – Pluto

+0

RegEx отлично работает. Я бы предпочел использовать его, поэтому я также могу использовать его для сопоставления во время замены. Я просто не знал, как обрабатывать случай, когда строка начинается с «*». Спасибо! – fugged

+0

@Pluto Это может быть достигнуто так: 'matches = line.replace (/ \\ */g, ''). IndexOf (" * ")> = 0;' - а именно, удалить все обратные символы '*' s и посмотрите, есть ли какие-либо '*' left: D –

0

В вену The Greatest Regex Trick Ever, просто использовать изменение типа:

what I dont want | (what I do want) 

А затем проверьте truthiness группы (1)

Таким образом, регулярное выражение:

\\\*|([^\\]?\*) 

Demo

Имейте в виду, что обе стороны матча переделки; вы можете определить разницу, проверив группу (1) после матча.

Смежные вопросы