2013-06-26 3 views
2

Я пытаюсь соответствовать узел DTD, как этот текст:JavaScript RegEx - возвращает результат, но до сих пор не работает

<!ELEMENT note (to,from,body)> 

С этим регулярным выражением:

match(/<!ELEMENT\s?(.*?)\s?\(.*?\)>/i) 

и возвращает нужный текст + текст «note» - объясните, почему?

Кроме того, когда я удаляю оба или оба пустых пространства с каждой стороны текста «примечания», он все равно возвращает результат, и это не требуется. Может ли кто-нибудь объяснить, почему он это делает?

Вот мой тестовый файл:

<!ENTITY Aring "&amp;#197;" >, 
<!ENTITY aring "&amp;#229;" >, 
<!ENTITY agrave "&amp;#224;" >, 
<!ENTITY aacute "&amp;#225;" >, 
<!ATTLIST ARTICLE AUTHOR CDATA #REQUIRED>, 
<!ATTLIST ARTICLE EDITOR CDATA #IMPLIED>, 
<!ATTLIST ARTICLE DATE CDATA #IMPLIED>, 
<!ATTLIST ARTICLE EDITION CDATA #IMPLIED>, 
<!ELEMENT note (to,from,heading,body)>, 
<!ELEMENT to (#PCDATA)>, 
<!ELEMENT from (#PCDATA)>, 
<!ELEMENT heading (#PCDATA)>, 
<!ELEMENT body (#PCDATA)> 

Заранее спасибо за любую помощь!

+0

Итак, вы хотите только совместить «(to, from, body)»? Требуется ли элемент примечания? –

+0

Я хочу сопоставить весь узел, если он правильно отформатирован ... или любой узел подобной структуры, поэтому результатом в этом случае будет и null, если оригинальный струна был например. – user1360809

+0

Покажите нам, как вы используете это регулярное выражение - он работает. Что * * хотел? – Bergi

ответ

0

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

Тогда ваши пробелы необязательны (из-за ?) - следовательно, удаление их в строке не имеет значения. Просто удалите ? или сделайте его + (чтобы разрешено использовать более одного места).

Другая проблема заключается в том, что . может также соответствовать пробелам. Вы должны возможно быть немного более ограничительными (таким образом, вы можете также избежать ungreedy кванторов, которые обычно хуже по производительности):

/<!ELEMENT\s+\S*\s+\([^)]*\)>/i 

\S соответствует ничего, кроме пробела и [^)] соответствует ничего, кроме ) символов (это отрицается класс символов). На самом деле, вы можете исключить ( из \S, а также, потому что в противном случае он может уже соответствовать в скобки:

/<!ELEMENT\s+[^\s(]*\s+\([^)]*\)>/i 

Если note части должна содержать по крайней мере один символ, который вы должны сделать, что ясно в регулярное выражение, а также, с помощью + вместо *

/<!ELEMENT\s+[^\s(]+\s+\([^)]*\)>/i 

Если note часть является необязательной с другой стороны, моя ранняя версия требует, по крайней мере, 2 пространства (в связи с два \s+). В этом случае вы можете сгруппировать часть note вместе со следующим пространством и сделать его необязательным вместе. Таким образом вам нужно только пространство, если есть note. Для подавления захвата (так что вы не получите две строки снова), используйте (?:...) для группировки вместо (...):

/<!ELEMENT\s+(?:[^\s(]+\s+)?\([^)]*\)>/i 

Обратите внимание, что match все равно даст вам массив, содержащий строку, которую вы ищете (и вы можете ничего не сделаю), поэтому вам нужно будет получить доступ к нему с помощью [0].

+0

спасибо - это все равно похоже на удаленные пространства - любая идея почему? – user1360809

+0

@ user1360809 Да, я неправильно понял эту часть вашего вопроса и сейчас отредактировал свой ответ. –

+0

может подтвердить, что он работает! ;) Хотя синтаксис немного сложнее, я предпочитаю этот ответ на данный момент ... – user1360809

1

Ответ на оба заключается в том, что вы используете .*, который соответствует всем ноль или более раз.

Вместо этого используйте следующее регулярное выражение:

/<!(?:ELEMENT|ENTITY|ATTLIST)\s+\w+\s+.+>/i 

Proof the regular expression works

A fiddle to further demonstrate this works

и прекрасный образ, чтобы показать, как работает матч:

Regular expression image

Подводя итог, это соответствует строке <!, а затем ELEMENT или ENTITY или ATTLIST, а затем 1 или больше пробелов (\s+), за которыми следуют 1 или более символов слова (\w+), а затем 1 или более пробелов, за которыми следует одно или более символов, за которым следует закрывающая скобка.

+0

этот не работал для меня ... – user1360809

+0

Как так? Демо работает. –

+0

не знаю - я скопировал RegEx напрямую, и он ничего не возвращает! – user1360809

1

Предоставления нотной части фиксирован:

var node = '<!ELEMENT note (to,from,body)>'; 
node.match(/<!ELEMENT note \(.+,.+,.+\)/); // Will alert the whole element 

var invalidNode = '<!ELEMENTnote (to,from,body)>'; 
invalidNode.match(/<!ELEMENT note \(.+,.+,.+\)/); // Will return null 

См: http://jsfiddle.net/a5KkF/

2

Вот что вы регулярное выражение выглядит, глядя на него через automaton:

Regular expression image

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

  1. "<!ELEMENT note (to,from,body)"
  2. "note"

, но он также будет соответствовать другой вид строки, как:

  • <!ELEMENT%e
(jmopV|)
  • <!ELEMENT r()

, которые не являются хорошо сформированными тегами.

Так что лучше хотите сделать more precise regex , как:

<!ELEMENT\s+\w+\s+\((\w+, ?)*\w+\)> 
  • вот то, что регулярное выражение соответствует:
    • текст <!ELEMENT
    • \s+ один или больше пространства
    • \w+ один или несколько слов характер
    • \s+ один или больше пространства
    • \( реальная скобка
    • ( начало группы
    • \w+ или более в слове характер
    • , запятая
    • ? один или нулевое пространство (может be * ноль или более пробелов)
    • )* конец группы, что gro до подкрепляются ноль или более раз
    • \w+ один или более в слове характер
    • (вы можете добавить \s*, если вы хотите, чтобы соответствовать дополнительные пробелы перед закрывающей скобкой)
    • \) закрывающая скобка характер
    • (вы можете добавить \s*, если вы хотите, чтобы соответствовать дополнительные пробелы до конца тега)
    • > закрывающий тег персонажа

Regular expression image

Затем, когда вы делаете match(/<!ELEMENT\s+\w+\s+\((\w+, *)*\w+\)>/i), вы все равно получите две группы:

  1. "<!ELEMENT note (to,from,body)>"
  2. "from,"

и вы должны получить первую группу, вам просто нужно получить первый элемент возвращаемого массива:

var match = "<!ELEMENT note (to,from,body)>".match(/<!ELEMENT\s+\w+\s+\((\w+, *)*\w+\)>/i); 
if (match !== null) 
    match = match[0]; 

и если вы хотите использовать объект регулярного выражения, чтобы сделать так:

pattern = new RegExp(/<!ELEMENT\s+\w+\s+\((\w+, *)*\w+\)>/i) 
match = pattern.exec(text) 
if (match !== null) 
    match = match[0] 

, что поможет вам первую группу матча (который является полное совпадение).

ПОСЛЕ EDIT:

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

<!ENTITY Aring "&amp;#197;" >, 
<!ENTITY aring "&amp;#229;" >, 
<!ENTITY agrave "&amp;#224;" >, 
<!ENTITY aacute "&amp;#225;" >, 
<!ATTLIST ARTICLE AUTHOR CDATA #REQUIRED>, 
<!ATTLIST ARTICLE EDITOR CDATA #IMPLIED>, 
<!ATTLIST ARTICLE DATE CDATA #IMPLIED>, 
<!ATTLIST ARTICLE EDITION CDATA #IMPLIED>, 
<!ELEMENT note (to,from,heading,body)>, 
<!ELEMENT to (#PCDATA)>, 
<!ELEMENT from (#PCDATA)>, 
<!ELEMENT heading (#PCDATA)>, 
<!ELEMENT body (#PCDATA)> 

так что вы хотите регулярное выражение, которое выглядит как этот:

/<!ELEMENT\s+\w+\s+\((\#?\w+,\s*)*\#?\w+\s*\)\s*>/ 

Regular expression image

look it up here

var match = "<!ELEMENT note (to,from,body)>".match(/<!ELEMENT\s+\w+\s+\((\#?\w+,\s*)*\#?\w+\s*\)\s*>/i); 
if (match !== null) 
    match = match[0]; 

там соответствует только <!ELEMENT... узлы, а не <!ATTLIST... или <!ENTITY... узлов. Для них match будет равно null. Для узлов <!ELEMENT... они будут содержать полную строку совпадающего узла.

+0

У меня получилось отличное впечатление, что ОП не хотел сопоставлять две группы, только одну. –

+0

это, похоже, не работает, отличные изображения! Я попытался использовать это: 'var testMatch = dtdNodes [i] .match (/ /i);' – user1360809

+0

странный, ve try: 'js> matches = ''. match (/ /i) [0]; 'и возвращает' '" '. Хотя, я не уверен в моем примере «нового RegExp». – zmo