2013-08-07 3 views
0

У меня есть список из 3000 или около того IP-адресов, которые были результатом вывода pdsh через dshback -c, который форматирует вывод в читаемом формате. Мне нравится читаемость dshback -c, но проблема заключается в том, что IP-адреса с общими октетами сворачиваются для экономии места. Мне нужно иметь полный IP-адрес для остальной части моего проекта.Использование BASH, как я могу расширить список IP-адресов PDSH?

Есть простой способ преобразовать этот вход:

192.168.38.[217,222],192.168.40.215,192.168.41.[219-222] 

к этому выходу:

192.168.38.217,192.168.38.222,192.168.40.215,192.168.41.219,192.168.41.220,192.168.41.221,192.168.41.222 

Я думал СЭД может быть использована непосредственно, но я не уверен, как хранить общие октеты в переменной. По этой причине, я считаю, что сценарий bash должен использоваться вместе с sed. Любая помощь или точки в правильном направлении были бы оценены.

ответ

1

Если вы можете изменить вход, вы можете использовать следующие формы:

echo 192.168.38.{217,222} 192.168.40.215 192.168.41.{219..222} | tr ' ' ',' 

В противном случае вы можете изменить его с помощью команды и Eval:

eval echo $(echo '192.168.38.[217,222],192.168.40.215,192.168.41.[219-222]' | \ 
sed 's/,/ /g;s/\[/{/g;s/]/}/g;s/-/../g;s/\({[0-9]\+\) \([0-9]\+}\)/\1,\2/g' | \ 
grep -v '[^0-9{}., ]') | tr ' ' ',' 

отметить, что Eval довольно опасно по аннулированным данным , поэтому я использую grep '[^0-9{}., ]', чтобы исключить любые неожиданные символы. sed в этой команде просто преобразует исходную строку в форму, указанную выше.

+0

Оба эти работы отлично. Благодарю. Я думаю, что я понимаю части sed и grep, но я не уверен в команде tr. Можете ли вы объяснить, почему он расширяет базы на фигурные скобки и 2 периода? Мне кажется, что он заменит пространство запятой.Я все еще не понимаю, прочитав страницу руководства. – user2659240

+0

Нам нужно 'tr' здесь, как после' echo' или 'eval echo', все IP-адреса разделены пробелами, и вам нужен список, разделенный запятыми. поэтому 'tr' просто заменяет пространство запятой. что касается расширения брекета, это стандартная функция bash. Вы можете прочитать об этом: https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html – rush

0

Если вы готовы использовать AWK, то вы можете попробовать этот

echo "192.168.38.[217,222],192.168.40.215,192.168.41.[219-222]" |sed 's/\[//g' | sed 's/\]//g' | awk -F, '{for(i=1;i<=NF;i++){n=split($i,a,".");IPL="";if(n>1){PIP=a[1] "." a[2] "." a[3];}else{IPL=PIP "." $i;}if(index(a[4],"-") > 0){x=0;split(a[4],b,"-");for(j=b[1];j<=b[2];j++){if(x==0){IPL=PIP "." j;x++;}else{IPL=IPL "," PIP "." j;}}}else if(index(a[4],",") > 0){split(a[4],b,",");IPL=PIP "." b[1] "," PIP "." b[2];}else{if(length(IPL)<=3){IPL=PIP "." a[4];}}printf("%s,",IPL);}}' 

Если вы заинтересованы в использовании этого я могу объяснить логику ...

0

Это один из способов его обработки чисто с Bash по мере необходимости. Нет awks, sed и другие вещи.

#!/bin/bash 

shopt -s extglob 
IFS=, 

while read -r LINE; do 
    OUTPUT=() 
    while [[ -n $LINE ]]; do 
     case "$LINE" in 
     +([[:digit:]]).+([[:digit:]]).+([[:digit:]]).+([[:digit:]])) 
      OUTPUT[${#OUTPUT[@]}]=$LINE 
      break 
      ;; 
     +([[:digit:]]).+([[:digit:]]).+([[:digit:]]).+([[:digit:]]),*) 
      OUTPUT[${#OUTPUT[@]}]=${LINE%%,*} 
      LINE=${LINE#*,} 
      ;; 
     +([[:digit:]]).+([[:digit:]]).+([[:digit:]]).\[+([[:digit:],-])\]*) 
      SET=${LINE%%\]*} 
      PREFIX=${SET%%\[*} 
      read -a RANGES <<< "${SET:${#PREFIX} + 1}" 
      for R in "${RANGES[@]}"; do 
       case "$R" in 
       +([[:digit:]])) 
        OUTPUT[${#OUTPUT[@]}]=${PREFIX}${R} 
        ;; 
       +([[:digit:]])-+([[:digit:]])) 
        X=${R%%-*} Y=${R##*-} 
        if [[ X -le Y ]]; then 
         for ((I = X; I <= Y; ++I)); do 
          OUTPUT[${#OUTPUT[@]}]=${PREFIX}${I} 
         done 
        else 
         for ((I = X; I >= Y; --I)); do 
          OUTPUT[${#OUTPUT[@]}]=${PREFIX}${I} 
         done 
        fi 
        ;; 
       esac 
      done 
      LINE=${LINE:${#SET} + 2} 
      ;; 
     *) 
      # echo "Invalid token: $LINE" >&2 
      break 
     esac 
    done 
    echo "${OUTPUT[*]}" 
done 

Для ввода

192.168.38.[217,222],192.168.40.215,192.168.41.[219-222] 

Запуск Баш temp.sh < temp.txt урожайности

192.168.38.217,192.168.38.222,192.168.40.215,192.168.41.219,192.168.41.220,192.168.41.221,192.168.41.222 

Это согласуется также с диапазонами. Если X меньше Y, например. 200-100, тогда он будет генерировать IPS с подмножествами от 200 до 100. Сценарий также может обрабатывать многострочные входы.

И он также должен работать со смешанными диапазонами, такими как [100,200-250].

0

С GNU AWK:

$ cat tst.awk 
BEGIN{ FS=OFS="," } 
{ 
    $0 = gensub(/(\[[[:digit:]]+),([[:digit:]]+\])/,"\\1+\\2","g") 
    gsub(/[][]/,"") 

    for (i=1;i<=NF;i++) { 
     split($i,a,/\./) 
     base = a[1] "." a[2] "." a[3] 
     range = a[4] 
     split(range,r,/[+-]/) 

     printf (i>1 ? "," : "") 
     if (range ~ /+/) { 
      printf "%s.%s", base, r[1] 
      printf "%s.%s", base, r[2] 
     } 
     else if (range ~ /-/) { 
      for (j=r[1]; j<=r[2]; j++) { 
       printf "%s.%s", base, j 
      } 
     } 
     else { 
      printf "%s.%s", base, range 
     } 
    } 
    print "" 
} 
$ 
$ awk -f tst.awk file 
192.168.38.217192.168.38.222,192.168.40.215,192.168.41.219192.168.41.220192.168.41.221192.168.41.222 

Нам нужен gensub(), чтобы изменить запятую внутри квадратных скобок различного характера (+), поэтому мы можем использовать запятую вне скобок в качестве разделителя полей и gensub() делает его специфичным для gawk.