Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Регулярка работает через раз. (https://javascript.ru/forum/misc/3687-regulyarka-rabotaet-cherez-raz.html)

Andrej_2 14.05.2009 12:31

Регулярка работает через раз.
 
Помогите пожалуйста отловить баг.

<script>

//-------------------------------------------------------------
var tshto_bylo = 'COLOR: #aaaaaa;color: #bbbbbb;color: #cccccc;color: #dddddd;color: #eeeeee;color: #ffffff"';

var tshto_najti = 'color';

var zamenjaemoe_znatshenie = 'test_projden';
//-------------------------------------------------------------


var reg = new RegExp('((^|;)\\s*)' + tshto_najti + '(\\s*:\\s*)([^;]*)((;)|$)','gi');

//((^|;)\s*)-начало строки или символ ";", за которыми могут быть пробелы
//(все это запомню и вставлю как подстроку "$1")


//(\s*:\s*)-возможные пробелы, за которым(и) идет символ ":", после чего опять возможны пробелы
//(все это запомню и вставлю как подстроку "$3")

//([^;]*)-возможен любой набор символов, кроме символа ";"

//((;)|$)-символ ";" или конец строки
//(символ ";" -если он есть - запомню и вставлю как подстроку "$6")

if (reg.test(tshto_bylo))
//--есть параметр, заменяю
{
var tshto_stalo = tshto_bylo.replace(reg,'$1' + tshto_najti + '$3' + zamenjaemoe_znatshenie + '$6');
}

window.alert(tshto_stalo);
</script>

Riim 14.05.2009 12:44

Так?

//-------------------------------------------------------------
var tshto_bylo = 'COLOR: #aaaaaa;color: #bbbbbb;color: #cccccc;color: #dddddd;color: #eeeeee;color: #ffffff"';
	 
var tshto_najti = 'color';
	 
var zamenjaemoe_znatshenie = 'test_projden';
//-------------------------------------------------------------
	 
	 
var reg = new RegExp('((^|;)\\s*)' + tshto_najti + '(\\s*:\\s*)([^;]*)(?=(;)|$)','gi');
if (reg.test(tshto_bylo)) {
	var tshto_stalo = tshto_bylo.replace(reg,'$1' + tshto_najti + '$3' + zamenjaemoe_znatshenie);
}
alert(tshto_stalo);

Kolyaj 14.05.2009 12:49

//-------------------------------------------------------------
var tshto_bylo = 'COLOR: #aaaaaa;color: #bbbbbb;color: #cccccc;color: #dddddd;color: #eeeeee;color: #ffffff"';
 
var tshto_najti = 'color';
 
var zamenjaemoe_znatshenie = 'test_projden';
//-------------------------------------------------------------
 
 
var reg = new RegExp('((^|;)\\s*)' + tshto_najti + '(\\s*:\\s*)([^;]*)','gi');
 
//((^|;)\s*)-начало строки или символ ";", за которыми могут быть пробелы
//(все это запомню и вставлю как подстроку "$1")
 
 
//(\s*:\s*)-возможные пробелы, за которым(и) идет символ ":", после чего опять возможны пробелы
//(все это запомню и вставлю как подстроку "$3")
 
//([^;]*)-возможен любой набор символов, кроме символа ";"
 
//((;)|$)-символ ";" или конец строки
//(символ ";" -если он есть - запомню и вставлю как подстроку "$6")
 
if (reg.test(tshto_bylo))
//--есть параметр, заменяю
{
var tshto_stalo = tshto_bylo.replace(reg,'$1' + tshto_najti + '$3' + zamenjaemoe_znatshenie);
}
 
window.alert(tshto_stalo);

Andrej_2 14.05.2009 20:53

Ребята, спасибо большое! Очень выручили! И первый, и второй варианты работают. А я все ломал голову, что не так сделал. Выкинул последнюю проверку вообще нафиг, т.к. знак ";" в моем случае не кретичен., а в другом месте его вообще пустил "под нож". Я не совсем (вернее, "совсем не") разбираюсь в JS, дохожу до всего методом проб и ошибок. Вот например такую же регулярку пытаюсь использовать для обратной задачи: в заданном тексте найти нужный параметр и взять его значение, которое упоминается последним (если параметр по ошибке написан несколько раз). Перепробовал все что прочитал, все не получается. В результате тупо прошелся регулярками и получил код, от которого самому стало страшно. Код работает, но не совсем: берет не последнее упоминание, а первое. Пробовал использовать в reg_2 ?!, но не получается. Пока рабочий вариант такой: (Просьба ногами не пинать, я еще только изучаю JS):

<script>
var text_stilja = 'COLOR: #aaaaaa;color: #bbbbbb;background-color: #xxxxxx;color: #cccccc;color: #dddddd;';
var tshto_najti = 'color';

var rezultat_3= '';//--по умолчанию пустой

var reg = new RegExp('((^|;)\\s*)' + tshto_najti + '(\\s*:\\s*)([^;]*)','gi');

   if (reg.test(text_stilja))
   //--есть параметр, заменяю
   {
     var rezultat_1= text_stilja.replace(reg,'<<<<<$4>>>>>');
      var reg_2 = new RegExp('(([^<]*)(<<<<<([^>]*)>>>>>)(.*))','i');
      var rezultat_2= rezultat_1.replace(reg_2,'<<<<<$3>>>>>');
      var reg_3 = new RegExp('(<|>)','g');
      rezultat_3= rezultat_2.replace(reg_3,'');

   }
      window.alert('Что было: \n\n'+text_stilja+'\n\n\n\n После первой регулярки (экранирую значения нужного мне параметра): \n\n'+rezultat_1+'\n\n\n\n После второй регулярки (надо взять последнее упоминание, отсекая все лишнее; как и в браузере, последнее определение одного и того же самое важное): \n\n'+rezultat_2+'\n\n\n\n После третьей регулярки (убираю экранирование): \n\n'+rezultat_3);

</script>



Пробовал reg_2 сделать так:

var reg_2 = new RegExp('(([^<]*)(<<<<<([^>]*)>>>>>)(?!([^<]*)<<<<<)([^>]*))','gi');


но не вышло. Как можно такое сделать?

Kolyaj 14.05.2009 21:18

Цитата:

Сообщение от Andrej_2
в заданном тексте найти нужный параметр и взять его значение, которое упоминается последним (если параметр по ошибке написан несколько раз)

Сначала не до конца понял задачу, и сделал для случая, если нужно удалить повторяющиеся описания.
var text_stilja = 'COLOR: #aaaaaa;color: #bbbbbb;background-color: #xxxxxx;color: #cccccc;color: #dddddd; BACKGROUND-COLOR: #FFF';
var styleNames = {};
alert(text_stilja.replace(/([-a-z]+):([^;]*);?/ig, function(match, name) {
    name = name.toLowerCase();
    if (styleNames[name]) {
        return '';
    } else {
        styleNames[name] = true;
        return match;
    }
}))


А для вашего случая:
var text_stilja = 'COLOR: #aaaaaa;color: #bbbbbb;background-color: #xxxxxx;color: #cccccc;color: #dddddd   ; BACKGROUND-COLOR: #FFF';
var match = text_stilja.match(/.*(?:^|;)\s*color:\s*([^;]*)/i);
if (match)
    alert('"' + match[1] + '"');
Только тут правые пробелы у значения обрезаться не будут.

Andrej_2 14.05.2009 21:33

Да! Чувствуется рука профессионала! Снимаю шляпу!


Только вот у меня с match и пр. никак не получалось именно потому, что не мог вставить переменную. Т.е. вместо color должна быть tshto_najti . А в таком случае

var match = text_stilja.match(/'.*(?:^|;)\s*' + tshto_najti + ':\s*([^;]*)'/i);


уже не работает.

Kolyaj 14.05.2009 22:34

var match = text_stilja.match(new RegExp('.*(?:^|;)\\s*' + tshto_najti + ':\\s*([^;]*)', 'i'));

e1f 15.05.2009 12:20

только желательно квотить переменную tshto_najti, а то она вполне может оказаться "похожей" на регулярку. Примерно так:
var qReg = new RegExp(preg_quote(q), 'i');
function preg_quote(str) {
    if (!str||str.constructor!=String) return '';
    return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
}

Riim 15.05.2009 15:33

Цитата:

Сообщение от e1f
\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:

У меня так:
RegExp.escape = function(str) {
	return (str + '').replace(/([?!^$.(){}:|=[\]+\-\/\\*])/g, '\\$1');
};


Разница такая:
у вас нет символов "-" и "/"
у меня нет "<" и ">"

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

Можете обосновать символы "<" и ">" ?

e1f 15.05.2009 17:18

Да, "<" и ">" явно лишние, ступил я где-то. "-" где может покромсать - знаю, добавил себе :) А вот насчет "/"... Можете привести пример?

Riim 15.05.2009 18:33

Цитата:

Сообщение от e1f
А вот насчет "/"... Можете привести пример?

Так и знал, что на счет этого символа вы мне на слово не поверите.
Вспоминаем ситуации, когда код создается из строки:
eval('..../regexp/g....');
setTimeout('..../regexp/g....', 100);
setInterval('..../regexp/g....', 100);
new Function('..../regexp/g....');

И конкретный пример:
RegExp.trueEscape = function(str) {
	return (str + '').replace(/([?!^$.(){}:|=[\]+\-\/\\*])/g, '\\$1');
};

RegExp.falseEscape = function(str) {
	return (str + '').replace(/([?!^$.(){}:|=[\]+\-\\*])/g, '\\$1');
};

var char_ = '/';
var re = eval('/' + RegExp.trueEscape(char_) + '/g');

alert(
'sd/fl/ks/kfk'.replace(re, '@')
);

e1f 15.05.2009 19:55

Да, Вы правы. Добавил еще и это :)

Andrej_2 16.05.2009 17:52

Извините за задержку, были дела.

Kolyaj, спасибо огоромное! То, что надо!

e1f, хорошее дополнение, но у меня что-то ошибка все время вылетает. Может, я по незнанию что-то не так делаю?

var tshto_najti_new = new RegExp(preg_quote(tshto_najti), 'i');
function preg_quote(str)
 {
    if (!str||str.constructor!=String) return '';
    return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
}


var  rezultat = text_stilja.match(new RegExp('.*(?:^|;)\\s*' + tshto_najti_new + ':\\s*([^;]*)', 'i'));


Riim, тут я вообще не понял, что куда вставлять. :)


Кстати, заметил такую особенность: если я полученную переменную rezultat в конце функции вставляю в другое поле, напр:

document.forms.kakaja_forma.zwet.value=rezultat[1];


то у меня символы в новом поле плохо выделяются мышкой. Подозреваю, что регулярка что-то еще за собой тащит, напр. перевод строки или еще что. Если rezultat задаю напрямую строкой, то все нормально.

Riim 16.05.2009 19:01

Это как так?
new RegExp('.*(?:^|;)\\s*' + (new RegExp(preg_quote(tshto_najti), 'i')) + ':\\s*([^;]*)', 'i')

Andrej_2 16.05.2009 20:53

Спасибо! Но все равно не выводит. Скорее всего, блокируют квадратные скобки в rezultat[1]:


<script>

function preg_quote(str)
{
if (!str||str.constructor!=String) return '';
return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
}

var text_stilja='COLOR: #aaaaaa;color: #bbbbbb;background-color: #xxxxxx;color: #cccccc;color: #dddddd;';

var tshto_najti = 'color';


var reg = new RegExp('.*(?:^|;)\\s*' + new RegExp(preg_quote(tshto_najti), 'i') + ':\\s*([^;]*)', 'i');

var rezultat = text_stilja.match(reg);


window.alert('Что было: \n\n'+text_stilja+'\n\n\n\n Последнее найденное значение: \n\n'+rezultat[1]);

</script>

Riim 16.05.2009 21:48

Вы меня неверно поняли. Я имел в виду, что у вас что-то странное написано.
Посмотрите, что выводится и какой RegExp у вас, в конечном счете, получается.

alert(
(new RegExp(preg_quote(tshto_najti), 'i')).toString()
);

Andrej_2 17.05.2009 12:22

Спасибо!

Получается дословно "/color/,i" Хотя, насколько я понимаю, должно быть "color". Если же переделываю вот так:

alert(preg_quote(tshto_najti));


то получается что надо, т.е. "color", и "опасные" символы при этом экранируются как надо.

Вставляю в регулярку:

var reg = new RegExp('.*(?:^|;)\\s*' + preg_quote(tshto_najti) + ':\\s*([^;]*)', 'i');
var rezultat = text_stilja.match(reg);


-- вылетает ошибка на rezultat[1]. При этом, если я в последнем случае вместо
+ preg_quote(tshto_najti) +
вставляю
+ tshto_najti +
, то все Ок. Значит, квадратные скобки в выводе rezultat[1] несовместимы с вставкой вместо переменной функции?

x-yuri 17.05.2009 15:15

Цитата:

вылетает ошибка на rezultat[1]
покажи полный текст, у меня ошибка не возникает
Цитата:

Значит, квадратные скобки в выводе rezultat[1] несовместимы с вставкой вместо переменной функции?
нет


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