我有一个3000个左右的IP地址列表,这些地址是通过dshback -c
传输的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可以直接使用,但我不确定如何将常见八位字节存储在变量中。出于这个原因,我相信bash脚本需要与sed一起使用。任何帮助或正确方向的点将不胜感激。
答案 0 :(得分: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
只会将原始字符串转换为我上面提到的格式。
答案 1 :(得分: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);}}'
如果你有兴趣使用这个我可以解释逻辑...
答案 2 :(得分:0)
这是根据需要纯粹使用Bash处理它的一种方法。没有awk,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&lt; 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]等混合范围。
答案 3 :(得分: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-具体