Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Что означает [^] (https://javascript.ru/forum/misc/49266-chto-oznachaet-%5B%5E%5D.html)

riva 05.08.2014 13:44

Что означает [^]
 
Объясните, что означает в регулярных выражения выражение [^] ?
Выражение [/[^ab]+/ в строке 'abcde' говорит о том, что не нужно обращать внимание на ab или оно говорит, что ab должно использоваться в поиске, но не включатся в результат?

WorM32 05.08.2014 13:54

[^ab]+ — "искать любые символы кроме a и b"

riva 05.08.2014 14:01

WorM32, Спасибо! Тогда получается, что в js регулярных выражений нет вовсе? Или я ошибаюсь?
Возможно, как-то сделать, чтобы я нашёл cde перед которыми обязательно идут ab?

WorM32 05.08.2014 14:09

riva,
В JS есть регулярные выражения, но "смотрящих назад" условий нет.

riva 05.08.2014 14:16

Цитата:

Сообщение от WorM32
В JS есть регулярные выражения

Нет.. Ну а если искать ab после которых обязательно идут cde, но не включая ab? Такого тоже нет?

WorM32 05.08.2014 14:25

Цитата:

Сообщение от riva (Сообщение 324379)
Нет.. Ну а если искать ab после которых обязательно идут cde, но не включая ab? Такого тоже нет?

http://javascript.ru/RegExp — Здесь все подробно и внятно расписано.

riva 05.08.2014 14:31

Цитата:

Сообщение от WorM32
Здесь все подробно и внятно расписано.

По ссылке информация лишь подтверждает, что регулярок в js не существует!

Erolast 05.08.2014 14:34

Цитата:

Возможно, как-то сделать, чтобы я нашёл cde перед которыми обязательно идут ab?
/ab(cde)/

Неожиданно, да?

ksa 05.08.2014 14:36

Цитата:

Сообщение от riva
По ссылке информация лишь подтверждает, что регулярок в js не существует!

Есть мнение что и циклы с условиями не работают... :lol:

riva 05.08.2014 14:44

Цитата:

Сообщение от Erolast
Неожиданно, да?

Мне непривычно, что возвращается массив со множеством элементов.
Цитата:

[ 'abcde', 'cde', index: 0, input: 'abcde' ]
Вроде я даже после Ваших слов за две минуты написал то, что начал ещё вчера :)
/(^|\n)"([\s\S]+)"($|\n)/

Спасибо Вам!

riva 05.08.2014 14:50

Вот с чем работаю я -
var str = '"abc"de"\n';

Эту строку мне нужно распарсить по следующим условиям -
Цитата:

1.Перед кавычкой обязательно должно находится начало строки или знак переноса строки \n.
2.Условие номер один не должно включаться в результат.
3.После закрывающей кавычки обязательно должно идти конец строки или знак переноса строки \n.
4.Условие номер три не должно включаться в результат.
Следуя этому плану у меня получилось -
var re = /(^|\n)"([\s\S]+)"($|\n)/

Получается, что третий элемент тот, что мне и был нужен.
Цитата:

[ '"abc"de"\n', '', 'abc"de', '\n', index: 0, input: '"abc"de"\n' ]
Может кто-нибудь сможет найти у меня ошибку или посоветовать чего?

Цитата:

Есть мнение что и циклы с условиями не работают...
Меня массив вместо единого результата путает.

edison 05.08.2014 16:32

/(?:^|\n)"([\s\S]+)"(?:$|\n)/

/^"([\s\S]+)"$/m

но это еще не конец)) '"abc"de"\n"abc"de"';))
ну допустим /^"([\s\S]+?)"$/m
но все равно не идеал)) , тебе виднее как именно нужно сделать дальше.
Из за отсутствия просмотра назад может придется еще что-то кроме регулярки делать. Хотя с \n^$ в этом плане проще, чем другими символами. По крайней мере в данном случае.

Aetae 05.08.2014 16:48

Вообще если есть уверенность что первый символ точно ковычка, то можно извратиться так:
alert('"abc"de"\r\n"abc"deвак"'.match(
    /[^"\r\n]+.*(?="$)/mg
))

riva 05.08.2014 17:34

Aetae , объясните пожалуйста выражение [^"\r\n].
А то я на него смотрю и понимаю, как - начать с кавычки, за которой идет перенос строки, но эти знаки не включать в результат. Так?
Или они говорят - вообще не обращать внимания на эти символы и выводить все, кроме них самих?
Это как бы и есть мой вопрос из-за которого я тему создал.

Aetae 05.08.2014 17:46

riva, был же ответ:
Цитата:

Сообщение от WorM32 (Сообщение 324371)
[^ab]+ — "искать любые символы кроме a и b"

^ - вне квадратных скобок - начало строки.
^ - внутри квадратных скобок - отрицание.

Как-то так, если упрощённо:
" - не подходит под [^"\r\n]+, пропускаем
a - подходит под [^"\r\n]+, начинаем получать результат
b - подходит под [^"\r\n]+, берём
c - подходит под [^"\r\n]+, берём
" - не подходит под [^"\r\n]+, переходим к .*(?="$), подходит под .*(?="$), берём
d - подходит под .*(?="$), берём
e - подходит под .*(?="$), берём
" - не подходит под .*(?="$) закончили первое совпадение
\r - не подходит под [^"\r\n]+, пропускаем
\n - не подходит под [^"\r\n]+, пропускаем
" - не подходит под [^"\r\n]+, пропускаем
a - подходит под [^"\r\n]+, начинаем получать результат
b - подходит под [^"\r\n]+, берём
c - подходит под [^"\r\n]+, берём
" - не подходит под [^"\r\n]+, переходим к .*(?="$), подходит под .*(?="$), берём
d - подходит под .*(?="$), берём
e - подходит под .*(?="$), берём
в - подходит под .*(?="$), берём
а - подходит под .*(?="$), берём
к - подходит под .*(?="$), берём
" - не подходит под .*(?="$) закончили второе совпадение

riva 05.08.2014 17:56

Цитата:

Сообщение от Aetae
riva, был же ответ:

Ну тогда мне это не подходит. Я же писал -
Цитата:

1.Перед кавычкой обязательно должно находится начало строки или знак переноса строки \n.
То есть, мне нужно, чтобы в условии обязательно было упоминание того, что перед открывающей кавычкой находится ^(начало строки) или \n(перенос строки), а у Вас получается, что Вы исключаете обязательные условия из выражения.

Aetae 05.08.2014 18:08

Ну нету в js regexp'ах просмотра назад, увы.
Так что придётся вам иметь дело с массивами:):
alert('"abc"de"\n'.match(
    /^"(.*)"$/m
))

riva 05.08.2014 18:19

Я пытаюсь комменты распарсить, но пока увы, безуспешно.
/**
 * Test-1
 * Test-2
 */

Вот так выглядит строка, если в файле только один коммент начатый с начала документа.
'/**\n * Test-1\n * Test-2\n */'

Пока остановился на ограничении количества звездочек, но ограничение в фигурных скобках у меня почему-то не работают..

Aetae 05.08.2014 18:41

alert(
'/**\n * Test-1\n * Test-2\n */'.replace(/^\/\*\*\s+\*\s+/,'').replace(/\s*\*\/$/,'').split(/[\r\n]+\s\*\s/)
)

riva 06.08.2014 12:30

Aetae, Спасибо! Но на Ваш пример, я пока только бегло глазами пробежал и всячески стараюсь от него убирать глаза. Я в js никогда не делал регуляки и мне хочется самому до этого дойти и во все разобраться, конечно с Вашей помощью.

У меня вот какой вопрос - как мне уже подсказали в это теме, если нужно из строки 'abcde' выбрать только символы 'cde', то нужно сделать так -
/ab(cde)/

И тогда элемент под индексом один будет той строкой, которую и хотели получить. Но стоит включить флаг g, как все перестает работать.
Как сделать, чтобы из строки выбрались только 'cde'? Желателньно какой-то универсальный вариант, так-как у меyz очень сложный пример.
var str = 'abcde abcde';
var re = /ab(cde)/g;

Aetae 06.08.2014 19:13

При флаге g в match - скобки игнорируются, ищет только полное вхождение строки.
Классическое решение: exec в цикле.(крайне рекомендую прочитать статью полностью)
Ленивое решение - replace:
var str = 'abcde abcde';
var re = /ab(cde)/g;
var outArray = [];
str.replace(re, function(matchedString, firstGroup, secondGroup){
    outArray.push(firstGroup);
});
alert(outArray);

riva 06.08.2014 23:37

Aetae, Спасибо! Почитал...Но честно сказать не понял.
regexp = /a+(b+(c+))/g
str = "abc aabbcc"

Цитата:

[ 'abc', 'bc', 'c', index: 0, input: 'abc aabbcc' ]
[ 'aabbcc', 'bbcc', 'cc', index: 4, input: 'abc aabbcc' ]
Почему в первый раз не выводится 'bcc' вместо 'bc'?

И у меня ещё маленький вопрос, который я объясню на ужатой миниатюре.
var str = 'DDD/**com m\nents*/ XXX /**comments*/III'
var re = /\/\*{1,2}([\s\S]+)\*\//g;

Строка иллюстрирует два блока комментариев с текстом между ними.
Выражение, в моем понимании, означает следующее - выбрать все между слешом, после которого идет от одной до двух звездочек и звездачкой, после которого идет слеш.
Цитата:

'com m\nents*/ XXX /**comments'
Но как видно, на деле выражение не останавливается на первом вхождении закрывающей скобки. Почему? Я предполагаю, что связанно это с [\s\S]+, но что с этим делать, я не знаю.

Возвращаясь к примеру... В первом случаи я наверное понял, хотя и могу ошибаться. Он находит 'abc' и начинает его разбирать дальше, 'bc', 'c'. Но если так, то почему во втором случаи он 'aabbcc', 'bbcc', то явно все начиналось с первой из двух 'a'/ И почему же он в следующий проход не вторую... Хотя я наверное понял!!! Он не строку гоняет, а выражение! Он начал с 'a+', потом 'b+' и затем 'c+'.
Я прав?

Aetae 07.08.2014 02:25

На счёт [\s\S]+ - множители(* +) по умолчанию жадные. Чтобы сделать поиск не жадным, нужно добавить в конец ?.

Если упростить: жадный продолжает поиск пока не находит совпадение максимально возможной длины, нежадный довольствуется самым первым.
Под \S(не-пробел) подходит и b и с :
alert([
    'abbbbbc'.match(/ab+\S/), //жадно
    'abbbbbc'.match(/ab+?\S/) //нежадно
].join('\n'))

riva 07.08.2014 14:14

Aetae, Спасибо! Ещё чуть-чуть и у меня получится:) Пишу чуть-чуть и смеюсь над этим, так-как каждый свой вопрос я сопровождаю мыслями, что получив на него ответ, я закончу. Но появляется новая проблема, которая сложнее и запутанней предыдущей. Вот и в этот раз так.

Чтобы было понятно, объясню полностью.. Вот какое выражение у меня получилось -
var re = /(^|\n)(?=\/)\/(?=\*{1,2})(?!\*{3,})\*{1,}(?=\n{1,1})(?!\n{2,})\n([\s\S]+?)(?=\*)\*(?=\/)\/(?=\n|$)\n|$/g;

Оно громоздкое, но по другому не как, ведь в комментариях может находится строка, которая содержит похожую на комментарии последовательность. Такой ситуации я лично никогда не встречал, но чтобы перестраховаться, сделал проверку на обязательную последовательность. Вот..
Вот имитатор самой строки -
var str = 'DDDDDDDDDDD\n/**\n * IIIIIIIIIII\n * IIIIIIIIIII\n * \n */\nXXXXXXXXXXX\n\n/**\n * NNNNNNNNNNNNN\n * NNNNNNNNNNNNN\n */\nEEEEEEEEEEE\n';

И вот код цикла -
var array = [];
var result =[];
var isHasNext = true;

while(isHasNext){
	if(array = re.exec(str)){
		result.push(array);
	}else{
		isHasNext = false;
	}
}

console.log(result);


И в ходе выполнения цикла, я получаю переполнение стека из-за того, что exec не возвращает null. Его глючит на -
[ '',
  undefined,
  undefined,
  index: 121,
  input: 'DDDDDDDDDDD\n/**\n * IIIIIIIIIII\n * IIIIIIIIIII\n * \n */\nXXXXXXXXXXX\n\n/**\n * NNNNNNNNNNNNN\n * NNNNNNNNNNNNN\n */\nEEEEEEEEEEE\n' ]


Почему так? Что с этим делать?

Добавлено:
Получилось! Спасибо Вам! Остался ещё один вопрос, но я сейчас поэкспериментирую и потом спрошу.

Aetae 07.08.2014 18:17

У-уу, маньячина.)

riva 07.08.2014 20:32

Пока остановился на этом -
var re = /(^|\n)(?=\/\*\*\n)\/\*\*\n([\s\S]+?) \*\/(?=\n|$)/

Задам ещё один вопрос на этом выражении.
Оно гласит - после начала строки или переноса строки, обязательно должно идти слеш и две звездочки, за которыми идет разрыв строки. И следом мне приходится опять писать эту же последовательность вне группы, чтобы исключить её из результата. И вопрос в том, можно и написать одновременно и обязательно и исключающи, чтобы не повторять одно и тоже дважды? У меня не получается так сделать...

Aetae 07.08.2014 20:42

(?=\/\*\*\n) можно просто убрать, т.к. не несёт смысла. И снова: в js нет просмотра назад.
Для успокоения души рекомендую почитать о полноценных regexp, с их (?<=) и прочими плюшками. Возможно тогда вам таки удастся смириться с ограниченностью regexp в javascript и вы заметите, что совершенно необязательно решать все проблемы одной регуляркой, а можно просто написать небольшую функцию в несколько последовательных действий.


Часовой пояс GMT +3, время: 03:23.