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

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, время: 19:50.