Bash:提取 IPv4 地址的四个部分之一

Bash:提取 IPv4 地址的四个部分之一

我们可以使用语法${var##pattern}${var%%pattern}提取 IPv4 地址的最后一部分和第一部分:

IP=109.96.77.15
echo IP: $IP
echo 'Extract the first section using ${var%%pattern}: ' ${IP%%.*}
echo 'Extract the last section using ${var##pattern}: ' ${IP##*.}

我们如何使用参数扩展提取 IPv4 地址的第二或第三部分?

这是我的解决方案:我使用数组并更改 IFS 变量。

:~/bin$ IP=109.96.77.15
:~/bin$ IFS=. read -a ArrIP<<<"$IP"
:~/bin$ echo ${ArrIP[1]}
    96
:~/bin$ printf "%s\n" "${ArrIP[@]}"
    109
    96
    77
    15

我还使用 、 和 命令编写了一些awk解决sed方案cut

现在,我的问题是:是否有一个更简单的解决方案参数扩展哪个不使用数组和IFS改变?

答案1

假设 IFS 的默认值,您可以使用以下命令将每个八位字节提取到它自己的变量中:

read A B C D <<<"${IP//./ }"

或者放入数组中:

A=(${IP//./ })

答案2

我确实意识到您特别要求一个 DID NOT 暂时重新定义的解决方案IFS,但我有一个您没有涵盖的甜蜜而简单的解决方案,所以这里是:

IFS=. ; set -- $IP

这个简短的命令会将您的 IP 地址元素放入 shell 的位置参数 $1, $2, $3, $4.但是,您可能需要先保存原始文件IFS,然后再恢复它。

谁知道?也许您会重新考虑并接受这个答案,因为它简洁有效。

(这之前被错误地给出为IFS=. set -- $IP

答案3

您的问题陈述可能比您预期的更自由一些。冒着利用漏洞的风险,这是解决方案穆鲁提到:

first=${IP%%.*}
last3=${IP#*.}
second=${last3%%.*}
last2=${last3#*.}
third=${last2%.*}
fourth=${last2#*.}
echo "$IP -> $first, $second, $third, $fourth"

这有点笨拙。它定义了两个一次性变量,并且不容易适应处理更多部分(例如,对于 MAC 或 IPv6 地址)。  谢尔盖·科洛迪亚兹内的回答启发我将上述概括为:

slice="$IP"
count=1
while [ "$count" -le 4 ]
do
    declare sec"$count"="${slice%%.*}"
    slice="${slice#*.}"
    count=$((count+1))
done

这集合sec1sec2和,可以通过以下方式sec3验证sec4

printf 'Section 1: %s\n' "$sec1"
printf 'Section 2: %s\n' "$sec2"
printf 'Section 3: %s\n' "$sec3"
printf 'Section 4: %s\n' "$sec4"
  • while循环应该很容易理解——它迭代四次。
  • Sergiy 选择了slice一个变量的名称来代替我的第一个解决方案(上面)中的last3和。last2
  • declare sec"$count"="value"是一种分配给sec1, sec2,的方法sec3,当是, ,和sec4 时。有点像,但更安全。count1234eval
  • value, "${slice%%.*}", 类似于我原来的答案分配给first,second和 的值third

答案4

使用 zsh,您可以嵌套参数替换:

$ ip=12.34.56.78
$ echo ${${ip%.*}##*.}
56
$ echo ${${ip#*.}%%.*}
34

这在 bash 中是不可能的。

相关内容