0

dshback -c私は 3000 ほどの IP アドレスのリストを持っています。これは、出力を読み取り可能な形式にフォーマットするためにパイプされた pdsh 出力の結果でした。の読みやすさは気に入ってdshback -cいますが、問題は、共通のオクテットを持つ IP がスペースを節約するために折りたたまれていることです。プロジェクトの残りの部分では、完全な IP アドレスが必要です。

この入力を変換する簡単な方法はありますか:

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

sed を直接使用できると思っていましたが、共通のオクテットを変数に格納する方法がわかりません。このため、sed とともに bash スクリプトを使用する必要があると思います。正しい方向への助けやポイントをいただければ幸いです。

4

4 に答える 4

1

入力を変更できる場合は、次のフォームを使用できます。

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

それ以外の場合は、コマンドと評価で変更できます。

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このコマンドでは、元の文字列を上記の形式に変換するだけです。

于 2013-08-07T05:23:44.377 に答える
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);}}'

これを使用することに興味がある場合は、ロジックを説明できます...

于 2013-08-07T06:08:48.913 に答える
0

これは、必要に応じて純粋に Bash で処理する 1 つの方法です。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]

bash 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 の場合、200 ~ 100 のサブセットで IPS が生成されます。スクリプトは複数行の入力も処理できます。

また、[100,200-250] のような混合範囲でも機能するはずです。

于 2013-08-07T06:15:12.430 に答える