Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Логика регулярных выражений (https://javascript.ru/forum/events/29495-logika-regulyarnykh-vyrazhenijj.html)

Overflow 30.06.2012 13:00

Логика регулярных выражений
 
Товарищи форумчане! Помогите, пожалуйста, понять логику работы регулярки на данном примере:

На вход подается ссылка на картинку определенного формата. На выходе должна выйти ссылка без протокола и query_string.

Пример: подаем http://site.ru/folder/picture.jpg?query&string или https://site.ru/folder/picture.jpg
На выходе получаем site.ru/folder/picture.jpg

Код:
if(document.getElementById('element_input').value.toLowerCase().indexOf('://', 0) > -1){
	picture = document.getElementById('element_input').value.match(/\:\/\/(.+?)\.(jpg|jpeg|png|bmp|gif)/i);
}else{
	picture = document.getElementById('element_input').value.match(/(.+?)\.(jpg|jpeg|png|bmp|gif)/i);
}

// на выходе picture[1] + "." + picture[2]


Да, этот код рабочий, но.. можно его как-то усовершенствовать убрав поиск через indexOf и переместив его в само регулярное выражение?
Попытки вроде
picture = document.getElementById('element_input').value.match(/(?:\:\/\/)??(.+?)\.(jpg|jpeg|png|bmp|gif)/i);

возвращают picture[1] вместе с возможным ://, а так быть не должно (должна быть "чистая" ссылка на картинку).

Собственно вопросы:
1. Почему picture[1] захватывает ://?
2. Как это исправить?

Заранее спасибо!

Deff 30.06.2012 13:54

Overflow,
Приведите реальные примеры двух трёх входных строк и что желаем видеть на выходе

Overflow 30.06.2012 22:36

input: http://cs315420.userapi.com/v3154206...u-OE.jpg?ololo
output: cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg

input: https://cs315420.userapi.com/v315420...?ololo&trololo
output: cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg

input: cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo
output: cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg

input: cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jPg
output: cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jPg

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

Deff 30.06.2012 23:12

<script type="text/javascript">
function InputTST(select) {
 var str = document.getElementById(select).value;
 str2=str.replace(/\s*(?:http:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //
 if(RegExp["$2"]!='') return str2;
 return false;
}
</script>
<input size="73" id="element_input" type="text" value=" cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo" /> <button type="button" onclick="alert('\''+InputTST('element_input')+'\'')">Test</button>

Overflow 01.07.2012 01:36

Спасибо за ответ! Не подскажите, почему часть с http
str2=str.replace(/(?:http:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //

работает на ура, а с отслеживанием "://" без символов букв
str2=str.replace(/(?:\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //

"бракует" ("http://" помещается в $1, первая группировка её не видит)? Интересует именно почему :// игнорируются первым группированием, а если группировать http:// - то нет.

Deff 01.07.2012 02:17

Цитата:

Сообщение от Overflow
"бракует" ("http://" помещается в $1, первая группировка её не видит)? Интересует именно почему :// игнорируются первым группированием, а если группировать http:// - то нет.

Ничо не понял - приведите входные варианты и выходные

Может так ?
str2=str.replace(/(?:.*?:?\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //

devote 01.07.2012 10:37

Цитата:

Сообщение от Overflow
"бракует" ("http://" помещается в $1, первая группировка её не видит)? Интересует именно почему :// игнорируются первым группированием, а если группировать http:// - то нет.

потому что вы делаете replace а не match
var a = "http://cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo";
alert( a.replace( /(?:http(?:s)?)?(?::\/\/)?(.*?\.(?:jpg|jpeg|png|bmp|gif)).*/gi, '$1' ) );

var a = "https://cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo";
alert( a.replace( /(?:http(?:s)?)?(?::\/\/)?(.*?\.(?:jpg|jpeg|png|bmp|gif)).*/gi, '$1' ) );

var a = "://cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo";
alert( a.replace( /(?:http(?:s)?)?(?::\/\/)?(.*?\.(?:jpg|jpeg|png|bmp|gif)).*/gi, '$1' ) );

var a = "cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo";
alert( a.replace( /(?:http(?:s)?)?(?::\/\/)?(.*?\.(?:jpg|jpeg|png|bmp|gif)).*/gi, '$1' ) );

Overflow 01.07.2012 12:20

devote, Deff, спасибо за ответы!


Цитата:

Сообщение от devote (Сообщение 185562)
потому что вы делаете replace а не match

Пример:
<script type="text/javascript">
function InputTST(select) {
 var str = document.getElementById(select).value;
str2=str.replace(/(?:.*\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2');
//str2=str.replace(/(?:\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2');

 if(RegExp["$2"]!='') return str2;
 return false;
}
</script>
<input size="73" id="element_input" type="text" value="https://cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo" /> <button type="button" onclick="alert('\''+InputTST('element_input')+'\'')">Test</button>

Но ведь если убрать .* в первой группе регулярка будет работать только тогда, когда :// будут в начале строки. Почему так? Ведь я /^ в начале не указывал? Пример:
<script type="text/javascript">
function InputTST(select) {
 var str = document.getElementById(select).value;
//str2=str.replace(/(?:.*\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2');
str2=str.replace(/(?:\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2');

 if(RegExp["$2"]!='') return str2;
 return false;
}
</script>
<input size="73" id="element_input" type="text" value="https://cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo" /> <button type="button" onclick="alert('\''+InputTST('element_input')+'\'')">Test</button>

Аналогично и с mathes (что я делаю не так?):
<script type="text/javascript">
function InputTST(select) {
 var str = document.getElementById(select).value;
//str2=str.replace(/(?:.*\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //
//str2=str.replace(/(?:\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //
var matches = str.match(/(?:\:\/\/)?(.+)\.(jpg|jpeg|png|bmp|gif)/i);

return matches[2] ? (matches[1] + "." + matches[2]) : false;
}
</script>
<input size="73" id="element_input" type="text" value="https://cs315420.userapi.com/v315420616/2bf/V7iMAyfu-OE.jpg?ololo&trololo" /> <button type="button" onclick="alert('\''+InputTST('element_input')+'\'')">Test</button>

Deff 01.07.2012 13:23

Overflow,
У devote, правильный вариант, посколь я тещу лишь наличие расширение, а devote выдаёт строку - если есть и расширения и начальные варианты строки

nerv_ 01.07.2012 20:28

Цитата:

Сообщение от Overflow
Да, этот код рабочий, но.. можно его как-то усовершенствовать убрав поиск через indexOf и переместив его в само регулярное выражение?

Зачем регулярное выражение, если можно, как Вы уже обозначили "дешево и сердито"?

Overflow 02.07.2012 00:55

nerv_,
Оптимизация :) Зачем делать в 2 операции то, что можно сделать в одну. А, так званый, "быдлокод" всегда можно успеть писать)

oneguy 02.07.2012 19:20

Цитата:

Сообщение от Overflow
Спасибо за ответ! Не подскажите, почему часть с http
str2=str.replace(/(?:http:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //

работает на ура, а с отслеживанием "://" без символов букв
str2=str.replace(/(?:\:\/\/)?(.*)\.(jpg|jpeg|png|bmp|gif).*$/ig,'$1.$2'); //

"бракует" ("http://" помещается в $1, первая группировка её не видит)? Интересует именно почему :// игнорируются первым группированием, а если группировать http:// - то нет.

Потому, что как в первом, так и во втором случае регулярка подходит с 0-го индекса, в первом случае подвыражение (?:http:\/\/)? ловит "http://", во втором случае (?:\:\/\/)? ловит "", то есть квантификатор сработал на 0.
Здесь важный момент: все возможности для подвыражения с квантификатором проверяются вначале, лишь если от текущего индекса ничего не нашлось, интерпретатор начинает искать со следующего индекса.
Цитата:

Сообщение от devote
потому что вы делаете replace а не match

Этот ответ неправильный, так как match ловит те же самые подстроки, что и replace.

Overflow 10.07.2012 20:51

Цитата:

Сообщение от oneguy (Сообщение 185884)
в первом случае подвыражение (?:http:\/\/)? ловит "http://", во втором случае (?:\:\/\/)? ловит ""

хм.. а почему во втором случае (?:\:\/\/)? ловит "", а не "://"?

oneguy 10.07.2012 20:57

Цитата:

Сообщение от Overflow
хм.. а почему во втором случае (?:\:\/\/)? ловит "", а не "://"?

Потому что поиск идёт с 0-го индекса, а там символ "h", а не ":". При этом поиск с 0-го индекса оказывается удачным, поэтому интерпретатор пропускает всю найденную подстроку.


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