我想从变量中提取 IP 和端口。我尝试过使用这个:
ADDR=1.2.3.4:12345
IP=${ADDR##:}
PORT=${ADDR%:}
Run Code Online (Sandbox Code Playgroud)
但是,这会将整个地址分配给两个变量。
如何将 IP 和端口存储到两个变量?
Art*_*ild 15
你错了,应该是这样的:
ADDR=1.2.3.4:12345
IP=${ADDR%:*}
PORT=${ADDR##*:}
Run Code Online (Sandbox Code Playgroud)
由于 IPv4 仅出现一次匹配:,因此在这种情况下,匹配第一个或最后一个出现并不重要。但是,对于 IPv6,最好匹配最后一次出现的端口。另外,看来你不小心切换了IP和PORT。
另请参阅此处:Bash 备忘单和Bash Hacker wiki
简而言之,子字符串删除的工作原理如下:
${variable#pattern}:从字符串开头删除第一个匹配项${variable##pattern}:从字符串开头删除最后一个匹配项${variable%pattern}:从字符串末尾删除,第一个匹配${variable%%pattern}:从字符串末尾删除最后一个匹配项*如果您只想匹配单词的一部分(不以空格分隔),则可能需要在模式中包含通配符 ( )。
由于您的字符串没有空格,也没有 shell 全局变量,即:
\naddr="1.2.3.4:12345"\nRun Code Online (Sandbox Code Playgroud)\n(顺便说一句,引用你的字符串是一个很好的做法)
\n您可以简单地使用 IP 和 PORT 填充数组,如下所示:
\na=(${addr//\\:/ })\nRun Code Online (Sandbox Code Playgroud)\n这会将:字符串中的每个内容替换为 内部的空格(),瞧!现在它是一个数组...这也适用于 MAC 地址之类的内容,但需要更多的数组元素。
注意:这适用于IPv4 \xe2\x80\xa6 对于IPv6,您可以这样做:
\naddr="[1fff:0:a88:85a3::ac1f]:8001"\naddr="${addr/\\[/}"\na=(${addr/\\]\\:/ })\nRun Code Online (Sandbox Code Playgroud)\n或者:您可以自动执行此操作以处理IPv4和IPv6,例如,条件如下:
\nif [[ "$addr" =~ [\\:]{2,} ]]\n then\n # It\'s IPv6 ... Do this\n addr="${addr/\\[/}"\n a=(${addr/\\]\\:/ })\n else\n # It\'s IPv4 ... Do this instead\n a=(${addr//\\:/ })\n fi\nRun Code Online (Sandbox Code Playgroud)\n然后,您可以像这样调用并打印数组元素:
\necho -e "IP: ${a[0]}\\nPORT: ${a[1]}"\nRun Code Online (Sandbox Code Playgroud)\n然后像这样简单地使用它:
\n$ addr="1.2.3.4:12345"\n$ a=(${addr//:/ })\n$ echo -e "IP: ${a[0]}\\nPORT: ${a[1]}"\nIP: 1.2.3.4\nPORT: 12345\nRun Code Online (Sandbox Code Playgroud)\n或者像这样处理空端口或没有端口:
\n$ addr="1.2.3.4:" # or even addr="1.2.3.4"\n$ a=(${addr//:/ })\n$ echo -e "IP: ${a[0]}\\nPORT: ${a[1]:-EMPTY}"\nIP: 1.2.3.4\nPORT: EMPTY\nRun Code Online (Sandbox Code Playgroud)\n就操作和评估而言......请参阅下面的演示:
\n$ addr="1.2.3.4:12345"\n$ # Populating an array "a" with the elements around the ":" from the string in "$addr"\na=(${addr//:/ })\n$ # Assigning array "a" elements to parameters\nip="${a[0]}"\nport="${a[1]}"\n$ # Assigning array "a" length(number of elements) to a parameter\nlen="${#a[@]}"\n$ # Printing array length\necho "${#a[@]}"\necho "$len"\n2\n2\n$ # Printing all array "a" elements\necho "${a[@]}"\n1.2.3.4 12345\n$ # Printing array "a" elements by index\necho "IP: ${a[0]} and PORT: ${a[1]}"\nIP: 1.2.3.4 and PORT: 12345\n$ # Printing array elements from parameters\necho "IP: $ip and PORT: $port"\nIP: 1.2.3.4 and PORT: 12345\n$ # Evaluating by array length\n[ "${#a[@]}" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"\n[ "$len" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"\nIP: 1.2.3.4 and PORT: 12345\nIP: 1.2.3.4 and PORT: 12345\n$ # Evaluating by array element/parameter string length "-z"(zero)\n[ -z "${a[1]}" ] && echo "IP: ${a[0]} and PORT: NA" || echo "IP: ${a[0]} and PORT: ${a[1]}"\n[ -z "$port" ] && echo "IP: $ip and PORT: NA" || echo "IP: $ip and PORT: $port"\nIP: 1.2.3.4 and PORT: 12345\nIP: 1.2.3.4 and PORT: 12345\n$ \n$ \n$ # This is a demonstration when there is only IP4 and no port \n$ addr="1.2.3.4"\n$ a=(${addr//:/ })\n$ ip="${a[0]}"\nport="${a[1]}"\n$ len="${#a[@]}"\n$ echo "${#a[@]}"\necho "$len"\n1\n1\n$ echo "${a[@]}"\n1.2.3.4\n$ echo "IP: ${a[0]} and PORT: ${a[1]}"\nIP: 1.2.3.4 and PORT: \n$ echo "IP: $ip and PORT: $port"\nIP: 1.2.3.4 and PORT: \n$ [ "${#a[@]}" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"\n[ "$len" == "2" ] && echo "IP: $ip and PORT: $port" || echo "IP: $ip and PORT: NA"\nIP: 1.2.3.4 and PORT: NA\nIP: 1.2.3.4 and PORT: NA\n$ [ -z "${a[1]}" ] && echo "IP: ${a[0]} and PORT: NA" || echo "IP: ${a[0]} and PORT: ${a[1]}"\n[ -z "$port" ] && echo "IP: $ip and PORT: NA" || echo "IP: $ip and PORT: $port"\nIP: 1.2.3.4 and PORT: NA\nIP: 1.2.3.4 and PORT: NA\nRun Code Online (Sandbox Code Playgroud)\n注意:虽然这个arr=(${parameter//delimiter/ })hack 是一个简单而好的事情,知道它可以完美地工作,如上所述,但你应该知道,如果你的字符串包含空格,它也容易出现 shell 分词,如果你的字符串包含通配符,它也容易出现 shell 通配符字符例如*...所以不建议这样做。
这是使用 bash 内置read命令的另一种方法:
IFS=: read IP PORT <<<"$ADDR"
Run Code Online (Sandbox Code Playgroud)
前任。(您应该避免为自己的 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
Run Code Online (Sandbox Code Playgroud)
此方法还将处理 :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
Run Code Online (Sandbox Code Playgroud)