2016-07-13 2 views
0

У меня есть текстовый файл, который содержит диапазоны адресов IP определяются следующим образом:Regex для создания нескольких IP-адресов из шаблона

10.30.8.4 
10.30.6.[10:12] 
10.30.[8:9].4 
[10:11].30.12.23 
[10:11].[28:29].[11:12].[22:23] 

, анализируя это с регулярным выражением, я ожидаю выхода быть

10.30.8.4 
10.30.6.10 
10.30.6.11 
10.30.6.12 
10.30.8.4 
10.30.9.4 
10.30.12.23 
11.30.12.23 
10.28.11.22 
10.28.11.23 
10.28.12.22 
10.28.12.23 
10.29.11.22 
10.29.11.23 
10.29.12.22 
10.29.12.23 
11.28.11.22 
11.28.11.23 
11.28.12.22 
11.28.12.23 
11.29.11.22 
11.29.11.23 
11.29.12.22 
11.29.12.23 

это то, что я до сих пор

$ips = Get-Content C:\temp\hosts.txt 
$regex = [regex] "(?:(?: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]?)" 

$regex.Matches($ips) | %{ $_.value } 

Это только получает первый IP-адрес, но не другие

+1

Возможно, я не понимаю, но это не так, как работает регулярное выражение. Вы можете сопоставить диапазоны сведенного ввода, но регулярное выражение не будет расширять их на IP-адреса. – briantist

+0

есть. Ты прав. Regex не решит проблему. Необходимо использовать какой-то цикл для расширения. – user330612

ответ

2

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

foreach ($line in (Get-Content D:\data.txt)) 
{ 
    if ($line -match ':') 
    { 
      $Left, $Range, $Right = $line -split '\[(.*)\]' 
      $start, $end = $Range -split ':' 
      $start..$end |% { "$Left$_$Right" } 
    } 
    else 
    { 
     $line 
    } 
} 

NB. «Диапазоны IP-адресов, определенные следующим образом», не определяют все, это всего лишь три примера. Я полностью догадался, что это значит. YMMV.


Редактировать для вашего редактирования: полностью отличается, если каждый фрагмент может быть диапазоном или нет. Я выработал функцию, чтобы сделать каждый элемент итерабельным, либо прямое число остается в виде числа, либо диапазон расширяется для всех элементов в диапазоне. Четыре вложенных циклов не так уж плохо, но я не хотел бы сделать это для IPv6 ...

Function Get-ExpandedBlock { 
    Param($block) 
    # Takes an IP chunk, either a number '10' or a range '[10:12]' 
    # Returns either the number: '10' or 
    # a PowerShell range over the input range: 10,11,12 

    if ($block -match ':') { 
     $start, $end = $block.Trim('[]') -split ':' 
     $start..$end 
    } else { 
     $block 
    } 
} 

$fullList = foreach ($line in (Get-Content D:\data.txt)) { 
    $a, $b, $c, $d = $line.Split('.') 

    foreach ($w in Get-ExpandedBlock $a) { 
    foreach ($x in Get-ExpandedBlock $b) { 
     foreach ($y in Get-ExpandedBlock $c) { 
     foreach ($z in Get-ExpandedBlock $d) { 
      "$w.$x.$y.$z" 
     } 
     } 
    } 
    } 
} 

$fullList 
+0

Tthis выглядит правильно. Благодарю. Одна небольшая проблема заключается в том, что она не работает, если в одной строке есть несколько расширений. ex: [10:11]. [12:13]. [20:23]. [100: 102] – user330612

+0

«* Вопрос, на который вы ответили? Это был не мой * настоящий * вопрос!/злой смех *; Да, мой код не будет обрабатывать вещи, которые вы не упомянули, - почему? – TessellatingHeckler

+0

мой плохой. обновил Q с ним сейчас – user330612

-1

Вы не можете, вообще говоря, использовать регулярные выражения для такого рода проблемы, где часть шаблона может отличаться, или, возможно, эта часть, с некоторым условием, принудительным по всей строке, как и в случае, если октет заменен диапазоном, OR THAT октет заменяется диапазоном. Это не фить.

Правильная среда для решения этой проблемы - AWK. Вы можете распознать любой из пяти образцов артефактов:

диапазон "." цифры "." цифры "." цифры
цифры "." ассортимент "." цифры "." цифры
цифры "." цифры "." ассортимент "." цифры
цифры "." цифры "." цифры "." диапазон
цифры "." цифры "." цифры "." цифры

и, в любом, но пятом, цикл над значениями, неявно указанными «диапазоном» для генерации всех адресов в семействе, с использованием псевдопеременных $ 1, $ 3, $ 5 и/или $ 7 соответственно для обозначения различных адресных частей.

0
List<String> resolveRange(String iprange) 
    { 
     List<String> ipList = new ArrayList<String>(); 
     if (iprange.indexOf("[") < 0) 
     { 
     ipList.add(iprange); 
     } 
     else 
     { 
     String[] sections = iprange.split("\\."); 
     Object[] output = new Object[4]; 
     int count = 1; 
     int index = 0; 
     for (String section : sections) 
     { 
      List<String> ips = resolve(section); 
      count *= ips.size(); 
      output[index++] = ips; 
     } 

     ipList = new ArrayList<String>(count); 
     List<String> section1 = (List<String>) output[0]; 
     List<String> section2 = (List<String>) output[1]; 
     List<String> section3 = (List<String>) output[2]; 
     List<String> section4 = (List<String>) output[3]; 

     for (String first : section1) 
     { 
      for (String second : section2) 
      { 
       for (String third : section3) 
       { 
        for (String four : section4) 
        { 
        ipList.add(new StringBuilder().append(first).append(".").append(second).append(".").append(third).append(".").append(four).toString()); 
        } 
       } 
      } 
     } 
     } 

     return ipList; 
    } 

    List<String> resolve(String section) 
    { 
     List<String> listString = new ArrayList<String>(); 

     if (section.indexOf("[") >= 0) 
     listString = parse(section); 
     else 
     listString.add(section); 
     return listString; 
    } 

    List<String> parse(String rangeString) 
    { 
     String[] arr = rangeString.replaceAll("[\\[\\]]", "").split(":"); 
     int start = Integer.valueOf(arr[0]); 
     int end = Integer.valueOf(arr[1]); 

     List<String> nums = new ArrayList<String>(); 
     while (start <= end) 
     { 
     nums.add(String.valueOf(start++)); 
     } 

     return nums; 
    } 
Смежные вопросы