Regex за съвпадение на [], но не и на \[\]

Как мога да получа всички съвпадения за [.*], но не и ако скобите са екранирани с обратна наклонена черта като \[.*\]?

Мога да използвам JavaScript функцията new RegExp("\\[.*\\]", "g"), за да получа всички [.*]. Как мога да изключа всички \[.*\] (екранирани скоби)?

Въвеждането изглежда така:

div\[data-custom-attribute='References'\][matchme]

В този случай регулярният израз трябва да съвпада с [matchme].


person MR.ABC    schedule 24.06.2013    source източник
comment
Защо не използвате регулярни изразни литерали, за да създадете регулярния израз, за ​​да премахнете необходимостта от двойно избягване на обратните наклонени черти? /\[.*\]/g   -  person hugomg    schedule 24.06.2013


Отговори (3)


http://rubular.com/r/16q3jSPHN0

[^\\](?:\]?(\[(.+?)\])) трябва да работи в повечето случаи.

Редактиране:

Изглежда, че това няма да съвпадне с \[test\][test], както Рори посочи. За това не мога да се сетя за добро решение без използване на множество регулярни изрази, но ако искате само един, опитайте това: http://rubular.com/r/QBqFAbqW9E

(?:[^\\](?:\]?(\[(.+?)\]))|((?:\]?(\[(.+?)\])))\\)

Групите за съвпадение ще бъдат попълнени в първите 3, ако се появи блок с екранирани скоби след обикновен блок, и в последните 3, ако се случи обратното.

Match 1
1.   
2.   
3.  [test]
4.  [test]
5.  test
Match 2
1.  [test]
2.  test
3.   
4.   
5.   
person dav    schedule 24.06.2013
comment
JavaScript не поддържа поглед назад, така че това е най-доброто, което можете да направите. Но ако JavaScript имаше, би било по-добре да замените [^\\] с (?<!\\), така че да можете да съпоставите низове, започващи с [, като [test]\[test\] (преди, след). - person Rory O'Kane; 24.06.2013
comment
@RoryO'Kane, прав си. Мисля, че би било разумно да се използват два израза, по един за всеки случай, поне що се отнася до JS. Като алтернатива актуализирах коментара си с един израз, който изглежда улавя и двата случая, но измества групираните резултати в зависимост от позицията на екранираните блокове. Не мога да измисля по-добро решение. - person dav; 24.06.2013
comment
Защо вашите тестови низове не съдържат никакви обратни наклонени черти? Една обратна наклонена черта в низ избягва следващия знак (ако има такъв), така че вашите единични обратни наклонени черти всъщност не са част от низа, което означава, че не тествате данните точно. В реален пример вашият първи регулярен израз не работи: jsfiddle.net/A6XBH/1 - person Ian; 24.06.2013
comment
Обърнете внимание, че в [foo][bar][baz] ще съответства само на bar. И да, в JS не можете да направите много по-добре от това да използвате (?:^|[^\\]) вместо [^\\]. - person Qtax; 24.06.2013
comment
@dav ще използвам 2 заявки за регулярен израз. как мога да получа 2 съвпадения вместо 1 за [data-custom-attribute='References'][matchme]? - person MR.ABC; 24.06.2013
comment
@Abc Погледнато назад, мисля, че би било по-добре, ако използвате един регулярен израз, за ​​да намерите всички екранирани блокове, да ги премахнете (напр. замени с "") и след това да използвате друг регулярен израз, за ​​да намерите всички регулярни блокове. Нещо подобно: jsfiddle.net/A6XBH/2 - person dav; 24.06.2013

Най-големият проблем е да знаете дали гледате екранирана скоба (\[) или скоба, която следва екранирана обратна наклонена черта (\\[). Това е достатъчно лесно, ако търсите само едно съвпадение:

/^[^\]\[\\]*(?:\\.[^\]\[\\]*)*(\[[^\]\[]+\])/

Първата част поглъща всички знаци, различни от обратни наклонени черти или квадратни скоби. Ако види обратна наклонена черта, хваща този и следващия знак, какъвто и да е той. Той повтаря този процес толкова пъти, колкото може, и когато вече не може да прави това, следващото нещо трябва да бъде стойността в скоби (или "таг"), която търсите. Заловен е в група №1.

Получаването на останалите тагове е по-трудно. За да останете в синхрон с данните, искате всяко следващо съвпадение да започва точно там, където е спряло предишното съвпадение. Много разновидности на регулярни изрази поддържат \G котвата точно за тази цел, но това не ни помага. JavaScript е в процес на приемане на флага /y, който прави по същество същото, но все още не можете да разчитате на това.

Ето заобиколно решение, което трябва да работи за случая:

/(?:^|\[[^\]\[]+\])[^\]\[\\]*(?:\\.[^\]\[\\]*)*(?=(\[[^\]\[]+\]))/g

Основният регулярен израз е същият, но групата за улавяне вече е вътре в поглед напред. Първият път започва да съвпада в началото на низа, както преди, но спира малко преди първия таг. Предварителният преглед потвърждава, че маркерът е наличен, но не го консумира. Следващото съвпадение започва с повторно съпоставяне на етикета, като този път го консумира. Междувременно етикетът също се записва в група #1, така че можете да получите достъп до него по обичайния начин.

var regex = /(?:^|\[[^\]\[]+\])[^\]\[\\]*(?:\\.[^\]\[\\]*)*(?=(\[[^\]\[]+\]))/g;
var match = regex.exec(subject);
while (match != null) {
    // tag is in match[1]
    match = regex.exec(subject);
}
person Alan Moore    schedule 24.06.2013

Използвайте неуловима група като [^\\]:

[^\\]\[.*[^\\]\]
person zessx    schedule 24.06.2013
comment
Мисля, че фразата, която търсите, е non-capturing group, но това, което имате там, всъщност е клас с отхвърлен символ и това не решава проблема. От една страна, вашият регулярен израз няма да съвпада с [test] в началото на низа, защото трябва да консумира знак преди отварящия [. Може да си мислите за отрицателен поглед назад, но JavaScript не ги поддържа. - person Alan Moore; 24.06.2013