Javascript-форум (https://javascript.ru/forum/)
-   Оффтопик (https://javascript.ru/forum/offtopic/)
-   -   Регулярные выражения головного мозга (https://javascript.ru/forum/offtopic/37857-regulyarnye-vyrazheniya-golovnogo-mozga.html)

qwerty-клавиатура 11.05.2013 03:32

Регулярные выражения головного мозга
 
function parseURL(str) {
        var re = /^(?:([a-zA-Z]+:)\/\/)?(?:([-+._a-zA-Z0-9]+)(?::([-+._a-zA-Z0-9]+))?@)?(([^-~!@#$%^^&*\(\)_+=\[\]{}:;'"\\,.\/?\s]+(?:[^~!@#$%^^&*\(\)_+=\[\]{}:;'"\\,.\/?\s]+[^-~!@#$%^^&*\(\)_+=\[\]{}:;'"\\,.\/?\s])*(?:\.[^-~!@#$%^^&*\(\)_+=\[\]{}:;'"\\,.\/?\s]+(?:[^~!@#$%^^&*\(\)_+=\[\]{}:;'"\\,.\/?\s]+[^-~!@#$%^^&*\(\)_+=\[\]{}:;'"\\,.\/?\s])*)*)(?::(\d+))?)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$/;
        var scheme = ['protocol', 'user', 'password', 'hostname', 'host', 'port', 'pathname', 'search', 'hash'], parts = re.exec(str);
        
        if (parts != null) {
            for (var i = 0, l = scheme.length, obj = {}; i < l;) {
                obj[ scheme[i] ] = parts[++i] != undefined ? parts[i] : '';
            }
            
            return obj;
        }
        
        return false;
    }


как неудивительно оно работает, но вот только делается все это намного проще. кто знает как?

devote 11.05.2013 11:08

странная регулярка и видимо не проверенная временем
Цитата:

Сообщение от qwerty-клавиатура
([a-zA-Z]+:)

протокол может содержать цифры, а тут только буквы
Цитата:

Сообщение от qwerty-клавиатура
(?:([a-zA-Z]+:)\/\/)?

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

Сообщение от qwerty-клавиатура
(?:([-+._a-zA-Z0-9]+)

имя пользователя часто имеет и другие символы
Цитата:

Сообщение от qwerty-клавиатура
(?::([-+._a-zA-Z0-9]+))?@)?

пароль, вообще может содержать все что угодно

про остальное вообще сложно сказать что намудрено.

Цитата:

Сообщение от qwerty-клавиатура
return false;

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

вот мой вариант написанный как то давно. хотя он и не претендует на идеал, ибо не проходил жестких тестов.
function parseURL(url) {
    var m = /(?:([\w0-9]+:))?(?:\/\/(?:(?:([^:]*):)?([^@]*)@)?(([^\/:\?#]+)(?:\:([0-9]+))?))?([^\?#]*)(?:(\?[^#]+)|\?)?(?:(#.*))?/.exec(url);
    return {
        protocol: m[1]||'',
        username: m[2]||'',
        password: m[3]||'',
        hostname: m[5]||'',
        host: m[4]||'',
        port: m[6]||'',
        pathname: m[7].replace(/^\s+/g,''),
        search: (m[8]||'').replace(/^\s+|\s+$/g,''),
        hash: m[9]||''
    }
}

qwerty-клавиатура 11.05.2013 12:55

все намного проще, что касается логина и пароля, то там у меня все по стандарту, протокол может содержать хекс %HH как и доменное имя(1-.%00 по стандарту валидное), но ни таких протокол ни доменных имен нет

function parseURL(s) {
    var a = document.createElement('a');
    a.href = s;
    
    var o = {
        hash: '',
        host: '',
        hostname: '',
        href: '',
        origin: '',
        pathname: '',
        port: '',
        protocol: '',
        search: ''
    }
    
    for (var p in o) {
        if ( o.hasOwnProperty(p) ) {
            o[p] = a[p];
        }
    }
    
    return o;
}

Aetae 11.05.2013 13:06

var a = document.createElement('a');
a.href = 'http://javascript.ru:999/forum/offtopic/37857-regulyarnye-vyrazheniya-golovnogo-mozga.html?neko#nya';
alert([
        'protocol: ' + a.protocol,
        'hostname: ' + a.hostname,
        'host: ' + a.host,
        'port: ' + a.port,
        'pathname: ' + a.pathname,
        'search: ' + a.search,
        'hash: ' + a.hash
].join('\n'))



upd: опоздал чутка.

devote 11.05.2013 14:14

Цитата:

Сообщение от qwerty-клавиатура
все намного проще

ага, ты во всех браузерах проверил? этот вариант в некоторых браузерах глючит, во вторых, тебе в твою ссылку могут быть подставлены домен/протокол и т.д. Тут все от браузера зависит.. Поэтому вариант очень плохой, я с ним уже ломал голову давно, когда писал библиотек History-API

qwerty-клавиатура 11.05.2013 17:31



// (#<identifier> rule)
function namedCaptures(re) { 
    var map = [];
    
    var ret = new RegExp( re.source.replace( /#<([^>]+)> /g, function(q, e) {
        map.push(e);        
        return '';
    } ), (re.global ? 'g' : '') + (re.ignoreCase ? 'i' : '') + (re.multiline  ? 'm' : '') ); 
    
    function assign(m) {
        if (m == null) {
            return m;
        }
        
        var i = map.length, j, o = {};
        
        while (i) {
            j = i;
            o[ map[--i] ] = m[j];
        }
        
        return o;
    }
    
    ret.exec = function(str) {
        return assign( RegExp.prototype.exec.call(this, str) );
    }
    
    return ret;
}

qwerty-клавиатура 11.05.2013 18:33

// (#<identifier> rule)
// re = captureNames( /^(#<protocol> [^:]*:)\/\/(?:(#<user> [-+\w.]+)(?::(#<password> [-+\w.]+))@)?(#<hostname> (#<host> [^:\\/?#]+)(?::(#<port> \d+))?)(#<path> [/\\][^?#]*)?(#<search> \?[^#]*)?(#<hash> #.*)?$/ );
// console.log( re.group(location.href) );
function captureNames(re) { 
    var names = [];
    
    re = new RegExp( re.source.replace( /#<(\w{1,32})> /g, function(q, e) {
        names.push(e);        
        return '';
    } ), (re.global ? 'g' : '') + (re.ignoreCase ? 'i' : '') + (re.multiline  ? 'm' : '') );
    
    re.names = names;
    
    function assign(m) {
        if (m == null) {
            return m;
        }
        
        var i = re.names.length, j, o = {};
        
        while (i) {
            j = i;
            o[ re.names[--i] ] = m[j];
        }
        
        return o;
    }
    
    re.group = function(str) {
        return assign( re.exec(str) );
    }
    
    return re;
}


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