【问题标题】:Handling IP and port in python and bash [closed]在 python 和 bash 中处理 IP 和端口 [关闭]
【发布时间】:2014-03-21 10:25:23
【问题描述】:

使用python和bash,我想完成两件事:

  1. 需要将 [fec2::10]:80 格式的 ipv6 地址和端口组合拆分为 fec2::10 和 80。

  2. 给定 IP 地址和端口组合,我需要确定 IP 是 v4 还是 v6 地址。例如:1.2.3.4:80 和 [fec2::10]:80

请提出一种方法。

谢谢!

示例代码:

#!/usr/bin/env python

import optparse

def main():
    server = "[fec1::1]:80"
    if server.find("[", 0, 2) == -1:
       print "IPv4"
       ip, port = server.split(':')
    else:
       print "IPv6"
       new_ip, port = server.rsplit(':', 1)
       print new_ip
       ip = new_ip.strip('[]')

    print ip
    print port

if __name__ == '__main__':
    main()

这适用于所有情况,除非指定输入时没有端口。例如:10.78.49.50 和 [fec2::10]

有解决这个问题的建议吗?

【问题讨论】:

  • 那么问题出在哪里?
  • 我的 bash 和 python 脚本将接收 IP:port 组合作为输入,脚本需要确定 IP 的地址族,然后拆分 IP 和端口。

标签: python bash ip-address


【解决方案1】:

假设your_input就像"[fec2::10]:80""1.2.3.4:80",很容易拆分端口,找出ip地址:

#!/usr/bin/env python3
from ipaddress import ip_address

ip, separator, port = your_input.rpartition(':')
assert separator # separator (`:`) must be present
port = int(port) # convert to integer
ip = ip_address(ip.strip("[]")) # convert to `IPv4Address` or `IPv6Address` 
print(ip.version) # print ip version: `4` or `6`

【讨论】:

  • ipaddress 模块只是 3.3 的新模块,如果有人在运行早期版本的 python 怎么办?我确实认为以这种方式查找版本更简单,但不要误会我的意思。 :)
  • @2rs2ts:你可以在早期版本上使用ipaddr-py
  • 啊,很高兴知道。不过,它仍然不是标准模块的一部分。
  • @J.F.Sebastian:我无法在我的脚本中同时使用 ipaddress 和 ipaddr-py 模块。对于 ipaddress,它说: Traceback(最近一次调用最后一次):文件“./ip_parse.py”,第 4 行,在 from ipaddress import ip_address ImportError: No module named ipaddress from ipaddress import ip_address
  • ...对于 ipaddr-py,它说:文件“./ip_parse.py”,第 5 行 from ipaddr-py import ip_address ^ SyntaxError: invalid syntax
【解决方案2】:

您可以使用urlparse(在 3.x 中称为 urllib.parse)将 URL 分隔为其每个组件:

>>> from urlparse import urlparse
>>> ipv4address = urlparse("http://1.2.3.4:80")
>>> ipv4address
ParseResult(scheme='http', netloc='1.2.3.4:80', path='', params='', query='', fragment='')
>>> ipv6address = urlparse("http://[fec2::10]:80")
>>> ipv6address
ParseResult(scheme='http', netloc='[fec2::10]:80', path='', params='', query='', fragment='')

然后您可以通过使用rfind 查找最后一个冒号的索引来拆分端口:

>>> ipv4address.netloc.rfind(':')
7
>>> ipv4address.netloc[:7], ipv4address.netloc[8:]
('1.2.3.4', '80')
>>> ipv6address.netloc.rfind(':')
10
>>> ipv6address.netloc[:10], ipv6address.netloc[11:]
('[fec2::10]', '80')

识别它是哪种类型应该像if ':' in that_split_tuple[0] 一样简单,对吧? (不是 100% 确定,因为我已经有一段时间没有了解如何在 URL 中编写 IPv6 地址了。)

最后,从您的 IPv6 地址中删除括号很简单,有很多方法可以做到:

>>> ipv6address.netloc[:10].replace('[', '').replace(']', '')
'fec2::10'
>>> ipv6address.netloc[:10].strip('[]')
'fec2::10'

编辑:由于您表示担心并非总是有端口号,因此您可以使用regular expression 大大简化:

>>> import re
>>> f = lambda(n): re.split(r"(?<=\]):" if n.startswith('[') else r"(?<=\d):", n)
>>> f(ipv4address.netloc)
['1.2.3.4', '80']
>>> f(ipv6address.netloc)
['[fec2::10]', '80']
>>> f("1.2.3.4")
['1.2.3.4']
>>> f("[fec2::10]")
['[fec2::10]']

(我在使用正则表达式时遇到了麻烦,因此使用了内联三元组。)

【讨论】:

  • 我在我的问题中添加了一个我编写的独立于模块的代码。它是不完整的。有什么建议吗?
  • @Maddy 好吧,此时我将为您编写一个正则表达式,但您需要告诉我,您是否总是会在 IPv6 地址周围加上括号,以及您是否将使用混合地址,例如::ffff:1.2.3.4.
【解决方案3】:

这是我想出的代码。它看起来冗长而费力,但它解决了所有可能的输入场景。任何压缩/更好的建议都是最受欢迎的:)

#!/usr/bin/env python

import optparse

def main():
    server = "[fec1::1]:80"

    if server.find("[", 0, 2) == -1:
       print "IPv4"
       if server.find(":", 0, len(server)) == -1:
          ip = server
          port = ""
       else:
          ip, port = server.split(':')
    else:
       print "IPv6"
       index = server.find("]", 0, len(server))
       if index == -1:
          print "Something wrong"
          new_ip = ""
          port = ""
       else:
          if server.find(":", index, len(server)) == -1:
             new_ip = server
             port = ""
          else:
             new_ip, port = server.rsplit(':', 1)
       print new_ip
       ip = new_ip.strip('[]')

    print ip
    print port

if __name__ == '__main__':
    main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多