регулярное выражение не показывает корректный результат для соответствия IPv6

Почему вторая локализованная строка не отображается правильно в консоли в этом примере?

Найдено 3 слова IPv6
2001: 0db8: 0000: 0000: 0000: FF00: 0042: 8329
2001: 0db8 :: --- неправильный вывод здесь
:: 1
#включают <iostream>
#включают <итератор>
#включают <строка>
#включают <регулярное выражение>

int main ()
{
std :: string s = "ipv4 модель 127.0.0.1 "
"в прямом эфире 2001: 0db8: 0000: 0000: 0000: ff00: 0042: 8329 "
"другой 2001: 0db8 :: ff00: 0042: 8329 "
"почтовый индекс :: 1 ";

std :: regex ex_ipv6 ("(([0-9a-FA-F] {1,4}:) {} 7,7 [0-9a-FA-F] {1,4} | ([0-9a-FA-F] {1 , 4}:) {} 1,7: | ([0-9a-FA-F] {1,4}:) {1,6}: [0-9a-FA-F] {1,4} | ([0-9a-FA-F] {1,4}:) {1,5} (: [0-9a-FA-F] {1,4}) {1,2} | ([0-9a -fa-F] {1,4}:) {1,4} (: [0-9a-FA-F] {1,4}) {1,3} | ([0-9a-FA-F] {1,4}:) {1,3} (: [0-9a-FA-F] {1,4}) {1,4} | ([0-9a-FA-F] {1,4} :) {1,2} (: [0-9a-FA-F] {1,4}) {1,5} | [0-9a-FA-F] {1,4}: ((: [0 -9а-FA-F] {1,4}) {1,6}) |: ((: [0-9a-FA-F] {1,4}) {1,7} |:) | fe80: (: [0-9a-FA-F] {0,4}) {0,4}% [0-9a-Za-Z] {1} |: :( FFFF (: 0 {1,4}) {0,1}:) {0,1} ((25 [0-5] | (2 [0-4] | 1 {0,1} [0-9]) {0,1} [0-9 ])) {3,3} (25 [0-5] |. (2 [0-4] | 1 {0,1} [0-9]) {0,1} [0-9]) | ( [0-9a-FA-F] {1,4}:) {1,4}: ((25 [0-5] | (2 [0-4] | 1 {0,1} [0-9] ) {0,1} [0-9])) {3,3} (25 [0-5] |. (2 [0-4] | 1 {0,1} [0-9]) {0, 1} [0-9]))");
auto words_ipv6_begin =
std :: sregex_iterator (s.begin (), s.end (), ex_ipv6);
auto words_ipv6_end = std :: sregex_iterator ();

if (std :: regex_search (s, ex_ipv6))
{
станд :: соиЬ << "Найденный "
<< std :: distance (words_ipv6_begin, words_ipv6_end)
<< " слова IPv6 \ n";

for (; words_ipv6_begin! = words_ipv6_end; words_ipv6_begin ++)
{
станд :: соиЬ <<  (* Words_ipv6_begin) .str () << "\ п";
}
}
}

1

Решение

Ваша проверка префикса принимает строку намного раньше, чем должна. Экспресс группа ([0-9a-fA-F]{1,4}:){1,7}: помечает адрес до перехода как действительный, использует строку и проверяет ::ff00:0042:8329 не соответствует ни одному оставшемуся образцу (и также считается отдельным адресом, если это так).

Пара замечаний о вашем использовании регулярных выражений. {7,7} может быть просто написано как {7}, IPv6-адреса должны быть [0-9a-f] когда представлен как base16, так что вы можете отказаться от [A-F] чеки.

#include <algorithm>
#include <iostream>
#include <regex>
#include <string>

// RFC5952 outlines canonical formatting for rendering IPv6 addresses as
// text. Hex values in an address SHOULD be lowercase.  Addresses can be
// shortened ONCE using the symbol '::'.  Whitespace is actually processed
// as part of the pattern, so use \\s to match whitespace.

int main() {
std::string ipv6 =
"(?:"// For the first 6 fields, match addresses with no jump (::)...
"  (?:                                              (?:[0-9a-f]{1,4}:){6}"// ...or a jump.
"  |                                             :: (?:[0-9a-f]{1,4}:){5}""  | (?:                         [0-9a-f]{1,4})? :: (?:[0-9a-f]{1,4}:){4}""  | (?: (?:[0-9a-f]{1,4}:){0,1} [0-9a-f]{1,4})? :: (?:[0-9a-f]{1,4}:){3}""  | (?: (?:[0-9a-f]{1,4}:){0,2} [0-9a-f]{1,4})? :: (?:[0-9a-f]{1,4}:){2}""  | (?: (?:[0-9a-f]{1,4}:){0,3} [0-9a-f]{1,4})? :: (?:[0-9a-f]{1,4}:)   ""  | (?: (?:[0-9a-f]{1,4}:){0,4} [0-9a-f]{1,4})? ::                      ""  )                                                                     "// Match the base10/16 addresses with no jump (suffix of above).
"  (?: [0-9a-f]{1,4} : [0-9a-f]{1,4}                                     ""      | (?: (?: 25[0-5] | 2[0-4][0-9] | [01]?[0-9]?[0-9])\\.){3}        ""        (?: (?: 25[0-5] | 2[0-4][0-9] | [01]?[0-9]?[0-9]))              ""  )                                                                     "// Not any above. Check to see if jump is between last 2 fields of addr.
"  | (?: (?:[0-9a-f]{1,4}:){0,5} [0-9a-f]{1,4})? :: [0-9a-f]{1,4}        ""  | (?: (?:[0-9a-f]{1,4}:){0,6} [0-9a-f]{1,4})? ::                      "")";
// End of ipv6 string pattern.

// Convert readable pattern above into the applicable regex pattern.
ipv6.erase(std::remove_if(ipv6.begin(), ipv6.end(), ::isspace), ipv6.cend());

std::regex ipv6_pattern(ipv6);
const std::string test = "ipv4 model 127.0.0.1 ""live 2001:0db8:0000:0000:0000:ff00:0042:8329 ""another 2001:0db8::ff00:0042:8329 ""zip form ::1 ";
auto result = std::sregex_iterator(test.cbegin(), test.cend(), ipv6_pattern);
const auto results_end = std::sregex_iterator();

if (result != results_end) {
std::cout << "Found "<< std::distance(result, results_end)
<< " IPv6 address matches.\n";

while (result != results_end) {
std::cout << (*result++).str() << '\n';
}
}
}

Приставка:

Found 3 IPv6 address matches.
2001:0db8:0000:0000:0000:ff00:0042:8329
2001:0db8::ff00:0042:8329
::1
1

Другие решения


По вопросам рекламы [email protected]