如何将以“:”分隔的IP和端口存储到两个变量中?

如何将以“:”分隔的IP和端口存储到两个变量中?

我想从变量中提取 IP 和端口。我尝试过使用这个:

ADDR=1.2.3.4:12345
IP=${ADDR##:}
PORT=${ADDR%:}

但是,这会将整个地址分配给两个变量。

我如何将 IP 和端口存储到两个变量中?

答案1

你理解错了,应该是这样的:

ADDR=1.2.3.4:12345
IP=${ADDR%:*}
PORT=${ADDR##*:}

由于 IPv4 中只有一个匹配的出现:,因此在这种情况下匹配第一个还是最后一个出现都无所谓。但是,对于 IPv6,最好匹配端口的最后一个出现。此外,您似乎不小心调换了 IP 和 PORT。

另请参见此处:Bash 备忘单Bash 黑客维基

简而言之,子字符串删除的工作原理如下:

  • ${variable#pattern}:从字符串开头删除第一个匹配项
  • ${variable##pattern}:从字符串开头删除最后一个匹配项
  • ${variable%pattern}:从字符串末尾删除第一个匹配项
  • ${variable%%pattern}:从字符串末尾删除最后一个匹配项

*如果只想匹配单词中未被空格分隔的部分,则可能需要在模式中包含通配符 ( )。

答案2

由于您的字符串没有空格也没有 shell glob,即:

addr="1.2.3.4:12345"

引用你的字符串是一种很好的做法

您可以简单地用 IP 和 PORT 填充一个数组,如下所示:

a=(${addr//\:/ })

这会将字符串中的每个字符替换为其中的:空格,瞧!它现在是一个数组... 这也适用于 MAC 地址之类的东西,但需要更多的数组元素。()

注意:这将适用于IPv4… 为了IPv6,你可以这样做:

addr="[1fff:0:a88:85a3::ac1f]:8001"
addr="${addr/\[/}"
a=(${addr/\]\:/ })

或者:你可以自动化处理这两个问题IPv4IPv6例如这样的情况:

if [[ "$addr" =~ [\:]{2,} ]]
  then
  # It's IPv6 ... Do this
  addr="${addr/\[/}"
  a=(${addr/\]\:/ })
  else
  # It's IPv4 ... Do this instead
  a=(${addr//\:/ })
  fi

然后,您可以像这样调用并打印数组元素:

echo -e "IP: ${a[0]}\nPORT: ${a[1]}"

然后只需像这样使用它:

$ addr="1.2.3.4:12345"
$ a=(${addr//:/ })
$ echo -e "IP: ${a[0]}\nPORT: ${a[1]}"
IP: 1.2.3.4
PORT: 12345

或者像这样处理空的或没有的 PORT:

$ addr="1.2.3.4:" # or even addr="1.2.3.4"
$ a=(${addr//:/ })
$ echo -e "IP: ${a[0]}\nPORT: ${a[1]:-EMPTY}"
IP: 1.2.3.4
PORT: EMPTY

至于操作和评估......请参见下面的演示:

$ addr="1.2.3.4:12345"
$ # Populating an array "a" with the elements around the ":" from the string in "$addr"
a=(${addr//:/ })
$ # Assigning array "a" elements to parameters
ip="${a[0]}"
port="${a[1]}"
$ # Assigning array "a" length(number of elements) to a parameter
len="${#a[@]}"
$ # Printing array length
echo "${#a[@]}"
echo "$len"
2
2
$ # Printing all array "a" elements
echo "${a[@]}"
1.2.3.4 12345
$ # Printing array "a" elements by index
echo "IP: ${a[0]} and PORT: ${a[1]}"
IP: 1.2.3.4 and PORT: 12345
$ # Printing array elements from parameters
echo "IP: $ip and PORT: $port"
IP: 1.2.3.4 and PORT: 12345
$ # Evaluating by array length
[ "${#a[@]}" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"
[ "$len" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"
IP: 1.2.3.4 and PORT: 12345
IP: 1.2.3.4 and PORT: 12345
$ # Evaluating by array element/parameter string length "-z"(zero)
[ -z "${a[1]}" ] && echo "IP: ${a[0]} and PORT: NA" || echo "IP: ${a[0]} and PORT: ${a[1]}"
[ -z "$port" ] && echo "IP: $ip and PORT: NA" || echo "IP: $ip and PORT: $port"
IP: 1.2.3.4 and PORT: 12345
IP: 1.2.3.4 and PORT: 12345
$ 
$ 
$ # This is a demonstration when there is only IP4 and no port 
$ addr="1.2.3.4"
$ a=(${addr//:/ })
$ ip="${a[0]}"
port="${a[1]}"
$ len="${#a[@]}"
$ echo "${#a[@]}"
echo "$len"
1
1
$ echo "${a[@]}"
1.2.3.4
$ echo "IP: ${a[0]} and PORT: ${a[1]}"
IP: 1.2.3.4 and PORT: 
$ echo "IP: $ip and PORT: $port"
IP: 1.2.3.4 and PORT: 
$ [ "${#a[@]}" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"
[ "$len" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"
IP: 1.2.3.4 and PORT: NA
IP: 1.2.3.4 and PORT: NA
$ [ -z "${a[1]}" ] && echo "IP: ${a[0]} and PORT: NA" || echo "IP: ${a[0]} and PORT: ${a[1]}"
[ -z "$port" ] && echo "IP: $ip and PORT: NA" || echo "IP: $ip and PORT: $port"
IP: 1.2.3.4 and PORT: NA
IP: 1.2.3.4 and PORT: NA

注意:虽然这个arr=(${parameter//delimiter/ })技巧很简单,而且很好用,如上所述,但是您应该知道,如果您的字符串包含空格,它也容易导致 shell 单词分裂;如果您的字符串包含通配符,它​​也容易导致 shell 通配符。例如*...所以不建议这样做。

答案3

以下是使用 bash 内置read命令的替代方法:

IFS=: read IP PORT <<<"$ADDR"

例如(您应该避免使用全大写的命名来作为您自己的 shell 变量 - 它们是非正式的保留名称):

$ addr=1.2.3.4:12345
$ IFS=: read ip port <<<"$addr"
$ printf 'IP is %s and PORT is %s\n' "$ip" "${port:-EMPTY}"
IP is 1.2.3.4 and PORT is 12345

此方法还可以处理缺少 :PORT 的情况:

$ addr=1.2.3.4
$ IFS=: read ip port <<<"$addr"
$ printf 'IP is %s and PORT is %s\n' "$ip" "${port:-EMPTY}"
IP is 1.2.3.4 and PORT is EMPTY

答案4

如果您不知道子字符串的数量或者子字符串的数量太多,您也可以使用数组。

例如,要将 MAC 地址拆分b0:25:a1:2d:b1:22成各个部分,您可以使用:

IFS=':' read -r -a mac <<< "b0:25:a1:2d:b1:22"

子字符串将"${mac[0]}"通过存储在数组元素中"${mac[5]}"

相关内容