2016-09-21 2 views
2

У меня есть два URL-адреса и вам нужно записать строку после расширения домена, если это двухсимвольная строка и заканчивается символом «/». До сих пор я получил это:Regex соответствует подгруппе, которая заканчивается на «/»

var t1 = "http://www.test.net/shop/test-3"; 
var t2 = "http://www.test.net/gb/shop/test-2"; 

var rgx = /\.([a-z]{0,3})\/([a-z]{2}\/)?/; 



console.log(rgx.exec(t1)); 

console.log(rgx.exec(t2)); 

Он выплевывает

[".net/", "net", undefined] 
[".net/gb/", "net", "gb/"] 

, который является правильным, за исключением того, я не хочу, чтобы захватить «гб /», но «гб» вместо этого. Есть идеи? Я совершенно застрял ..

ответ

0

Вы можете просто использовать слэш как lookahead, который не поставит его в группе захвата, как так (?=\/)

EDIT:, как Evaldas Raisutis упоминалось в комментарии, это не будет соответствовать два символа, если два символа - последнее вещь в URL-адресе, и нет косой черты, поэтому вместо (?=\/|$) можно использовать /или конец линии, тем самым делая эту часть опциональной. Который превращает картину в

\.([a-z]{0,3})\/([a-z]{2}(?=\/|$))? 

See in Regex101

var t1 = "http://www.test.net/shop/test-3"; 
 
var t2 = "http://www.test.net/gb/shop/test-2"; 
 
var t3 = "http://www.test.net/de/"; 
 
var t4 = "http://www.test.net/fr"; 
 

 
var rgx = /\.([a-z]{0,3})\/([a-z]{2}(?=\/|$))?/; 
 

 
console.log(rgx.exec(t1)); 
 
console.log(rgx.exec(t2)); 
 
console.log(rgx.exec(t3)); 
 
console.log(rgx.exec(t4));

+0

Итак, любые комментарии для downvote? – vlaz

+0

Не знаете, почему пустые голоса, но я закончил с этим. Кроме того, оказалось, что мне также необходимо сделать трейлинг-косую факультативу, так что закончил с /\.([az]{0,3})\/([az]{2}(?=\/|$))?/ –

+0

@EvaldasRaisutis да, если у вас есть другие после двух символов, вышеупомянутое регулярное выражение сработало бы, но не, если это последнее в URL. Я просто добавлю это в ответ для лучшей видимости. – vlaz

6

Метод можно использовать, используя группу захвата внутри необязательного не-захвата группы:

/\.([a-z]{0,3})\/(?:([a-z]{2})\/)?/ 
       ^^^^   ^^ 

См regex demo

var t1 = "http://www.test.net/shop/test-3"; 
 
var t2 = "http://www.test.net/gb/shop/test-2"; 
 
console.log(/\.([a-z]+)\/(?:([a-z]{2})\/)?/.exec(t1)); 
 
console.log(/\.([a-z]+)\/(?:([a-z]{2})\/)?/.exec(t2));

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

/^https?:\/\/[^\/]+\.([a-z]+)\/(?:([a-z]{2})\/)?/ 

См this regex demo

Детали:

  • ^ - начало строки
  • https?:\/\/ - это protocal часть (http:// или https://)
  • [^\/]+\.([a-z]+)\/ - соответствие доменная часть один или больше символов эр чем / затем ., а затем захватить TLD (1 или более букв, [a-z]+) в 1-й группе
  • (?:([a-z]{2})\/)? - необязательная последовательность:
    • ([a-z]{2}) - Группа 2 захватывая 2 строчных ASCII буквы
    • \/ - косая черта.

var t1 = "http://www.test.net/shop/test-3"; 
 
var t2 = "http://www.test.net/gb/shop/test-2"; 
 
console.log(/^https?:\/\/[^\/]+\.([a-z]+)\/(?:([a-z]{2})\/)?/.exec(t1)); 
 
console.log(/^https?:\/\/[^\/]+\.([a-z]+)\/(?:([a-z]{2})\/)?/.exec(t2));

+0

Я согласен с поиском первый '/' и идти оттуда. Это действительно более точно. Единственное, что я хотел бы отметить, это то, что имя домена может содержать более трех символов ('domain.info'), поэтому я бы удалил это ограничение. Предполагая, что URL-адрес обрабатывается (в отличие от свободного текста), тогда мы действительно хотим всего лишь между последним '.' и перед первым'/'. Это означает, что TLD является даже актуальным - если это не так, то просто получить все после первого и второго '/' достаточно. Хотя это может быть еще проще без использования регулярных выражений. – vlaz

+0

@vlaz: Спасибо за ценный комментарий, я обновил ответ. Здесь могут быть и другие улучшения, я просто не знаю, нуждается ли здесь OP :) –

+0

Правда, в зависимости от варианта использования, это может быть перебор. – vlaz

4

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

function parse(str){ 
 
    // Remove the domain extension and everything before that. 
 
    // Then return the first section of the rest, before `/` 
 
    return str.replace(/.+\.\w+\//, '') 
 
       .split('/')[0]; 
 
} 
 
console.log(parse("http://www.test.net/shop/test-3")); 
 
console.log(parse("http://www.test.net/gb/shop/test-2")); 
 
console.log(parse("http://www.test.net/nl"));

Таким образом, вы можете легко проверить длину возвращаемых результатов.

Regex объяснение:

.+\.\w+\/ 
.+ - matches any character (except newline) 
      Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy] 
\. - matches the character . literally 
\w+ - match any word character [a-zA-Z0-9_] 
      Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy] 
\/ - matches the character/literally 

Это регулярное выражение в основном захватывает все перед расширением домена, само расширение домена, и / позади него.