☰
jc --ip-address 解析器完全指南:将 IPv4/IPv6 地址字符串一键转换为结构化 JSON
2026/9/25 11:44:43 网站建设 项目流程
  • 开发工具

【免费下载链接】jc

CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

项目地址:https://gitcode.com/gh_mirrors/jc/jc
点击查看免费下载

本指南深入讲解 jc 项目的ip_address解析器:它能同时接受标准点分十进制与整数记法的 IPv4/IPv6 地址(含 CIDR 前缀与 Scope ID),并输出包含网段计算、地址分类、int/hex/bin 多进制转换的完整 JSON 结构。读完本文,你将掌握jc --ip-address的 CLI 用法、jc.parse('ip_address', ...)的模块调用方式、输出 Schema 中每一个字段的语义,以及底层如何基于 Python 标准库ipaddress实现。

解析器定位:面向"地址字符串"的通用转换器

jc(JSON Convert)是一个把常用命令行工具输出、文件类型和通用字符串转换为 JSON、YAML 或字典的 CLI 工具与 Python 库。ip_address是其中的一个"字符串类"解析器,专门处理纯粹的 IP 地址文本,而不是某个命令的输出。根据 jc/parsers/ip_address.py 中的元信息,该解析器:

  • 版本:1.5,作者 Kelly Brazil;
  • 兼容平台:linux、darwin、cygwin、win32、aix、freebsd;
  • 标签:standard、string、slurpable——其中slurpable意味着它可以配合 jc 的--slurp选项一次性解析多行地址。

由于它不依赖任何外部命令,只接受地址文本本身,非常适合在自动化脚本中快速把 IP 字符串"结构化",再交给jq等工具做过滤与统计。

两种调用方式:CLI 与 Python 模块

CLI 方式

将地址字符串通过标准输入管道传给 jc:

$ echo '192.168.1.1' | jc --ip-address

需要美化输出(pretty)时追加-p:

$ echo 192.168.2.10/24 | jc --ip-address -p

从 jc/lib.py 可以看出,'ip-address'被注册在解析器名称列表中,CLI 通过--ip-address长选项即可触发。

模块方式

在 Python 中调用jc.parse():

import jc result = jc.parse('ip_address', ip_address_string)

parse()是解析器的主入口,其函数签名定义在 jc/parsers/ip_address.py:

def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
参数类型说明
datastring待解析的地址文本(IPv4/IPv6,可含 CIDR、Scope ID,或直接是整数记法)
rawboolean为True时返回未处理的原始结构化数据
quietboolean为True时抑制警告信息(如平台兼容性提示)

函数内部会先调用jc.utils.compatibility()校验平台兼容性、用jc.utils.input_type_check()检查输入类型,再进入正式的解析逻辑。

支持的输入格式

根据文档说明,该解析器接受标准记法与整数记法两种形式的 IPv4/IPv6 地址,标准记法还可以附加 CIDR 子网掩码与 Scope ID:

输入形式示例说明
IPv4 标准地址192.168.1.1点分十进制
IPv4 带 CIDR192.168.2.10/24可计算网段、广播地址等
IPv4 点分掩码192.168.0.1/255.255.128.0测试用例 tests/test_ip_address.py 验证了这种写法,输出cidr_netmask为 17
IPv4 整数记法3232236042等价于192.168.2.10
IPv6 标准地址127:0:de::1支持::压缩写法
IPv6 带 CIDR127:0:de::1/96
IPv6 带 Scope ID127:0:de::1%128/96%后为接口 Scope ID(如%eth0、%128)
IPv6 整数记法1531727573536155682370944093904699393等价于127:0:de::1

从源码看,整数与字符串的判定发生在解析初期(jc/parsers/ip_address.py):解析器先尝试把data直接int()转换,失败则按字符串处理,因此两种记法可以无缝混用。

输出 Schema 全字段解析

文档给出了完整的 JSON Schema,所有字段按功能可分为五大组:

1. 版本与地址形态

字段类型说明
versionintegerIP 版本号,IPv4 为 4,IPv6 为 6
max_prefix_lengthinteger最大前缀长度,IPv4 为 32,IPv6 为 128
ipstring规范化后的裸地址(不带 CIDR)
ip_compressedstring压缩写法(IPv6 用::折叠连续零段)
ip_explodedstring展开写法(IPv6 每段补足 4 位十六进制)
ip_splitarray[string]按段拆分的地址列表:IPv4 为 4 个十进制数,IPv6 为 8 个四位十六进制段
scope_idstring/nullIPv6 接口 Scope ID,无则为null
ipv4_mappedstring/nullIPv4 映射地址(::ffff:x.x.x.x)中还原出的 IPv4,无则为null
six_to_fourstring/null6to4 地址(2002::/16)中内嵌的 IPv4,无则为null
teredo_clientstring/nullTeredo 地址中的客户端 IPv4,无则为null
teredo_serverstring/nullTeredo 地址中的服务器 IPv4,无则为null

2. 网络与主机范围

字段类型说明
dns_ptrstring反向 DNS PTR 记录名(IPv4 为in-addr.arpa,IPv6 为ip6.arpa)
networkstring网络地址
broadcaststring广播地址
hostmaskstring主机掩码(与子网掩码互补)
netmaskstring子网掩码
cidr_netmaskintegerCIDR 前缀长度(如/24为 24)
hostsinteger可用主机数(不含网络地址与广播地址)
first_hoststring第一个可用主机地址
last_hoststring最后一个可用主机地址

3. 地址分类标志(布尔)

字段说明
is_multicast是否为组播地址
is_private是否为私有地址(RFC 1918 等)
is_global是否为全球可达地址
is_link_local是否为链路本地地址
is_loopback是否为回环地址
is_reserved是否为保留地址
is_unspecified是否为未指定地址

4. 整数表示(int 子对象)

int下包含ip、network、broadcast、first_host、last_host五个整数字段,将各地址转为无符号大整数(IPv6 为 128 位整数,数值可达 39 位十进制)。

5. 十六进制与二进制表示(hex / bin 子对象)

  • hex:以冒号分隔的十六进制字节串(IPv4 为 4 组、IPv6 为 16 组),覆盖ip、network、broadcast、hostmask、netmask、first_host、last_host;
  • bin:固定长度的二进制字符串(IPv4 为 32 位、IPv6 为 128 位),覆盖同样的 7 个字段。

实战示例:六种典型输入输出

以下示例全部来自文档,是验证解析器行为的最佳素材,可直接复制运行。

示例 1:IPv4 + CIDR

$ echo 192.168.2.10/24 | jc --ip-address -p

输出要点:version: 4、network: 192.168.2.0、broadcast: 192.168.2.255、cidr_netmask: 24、hosts: 254、first_host: 192.168.2.1、last_host: 192.168.2.254;is_private: true;dns_ptr为10.2.168.192.in-addr.arpa;int.ip为3232236042,hex.ip为c0:a8:02:0a,bin.ip为11000000101010000000001000001010。

示例 2:IPv4 整数记法

$ echo 3232236042 | jc --ip-address -p

整数3232236042被还原为192.168.2.10。注意此时未提供 CIDR,因此cidr_netmask为 32、hosts为 1、network/broadcast/first_host/last_host均为地址本身、hostmask为0.0.0.0、netmask为255.255.255.255。

示例 3:IPv6 + CIDR + Scope ID

$ echo 127:0:de::1%128/96 | jc --ip-address -p

scope_id为128;version: 6、max_prefix_length: 128;ip_exploded为0127:0000:00de:0000:0000:0000:0000:0001;cidr_netmask: 96、hosts: 4294967294;is_global: true、is_reserved: true;dns_ptr为1.0.0.0.0.0...0.0.0.e.d.0.0.0.0.0.0.7.2.1.0.ip6.arpa。

示例 4:IPv6 整数记法

$ echo 1531727573536155682370944093904699393 | jc --ip-address -p

该 128 位整数被还原为127:0:de::1,此时cidr_netmask为 128、hosts为 1、hostmask为::、netmask为全ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff。

示例 5:IPv4 映射地址(IPv4-Mapped)

$ echo ::FFFF:192.168.1.35 | jc --ip-address -p

ipv4_mapped字段还原出192.168.1.35,ip_split同时包含 6 个 IPv6 段与 4 个 IPv4 十进制段(["0000", ..., "ffff", "c0a8", "0123"]的旧式输出,或含"192","168","1","35"的新式输出,取决于 Python 版本)。

示例 6:6to4 与 Teredo 地址

$ echo 2002:c000:204::/48 | jc --ip-address -p # 6to4 $ echo 2001:0000:4136:e378:8000:63bf:3fff:fdd2 | jc --ip-address -p # Teredo

6to4 示例的six_to_four为192.0.2.4;Teredo 示例的teredo_client为192.0.2.45、teredo_server为65.54.227.120。这些派生属性直接来自 Pythonipaddress标准库对特殊 IPv6 地址类型的内建识别。

源码实现:底层原理与边界处理

核心依赖:Python 标准库 ipaddress

解析器在 jc/parsers/ip_address.py 中导入了re、binascii与标准库ipaddress。整个转换过程围绕ipaddress.ip_interface()展开:它一次性完成地址合法性校验、CIDR 与掩码解析、网段/广播地址计算,并暴露scope_id、ipv4_mapped、sixtofour、teredo等属性。

Scope ID 的兼容处理

Python 3.9 之前的版本不支持 IPv6 地址带%scope的写法,源码用正则SCOPE_PATTERN = re.compile(r'%[a-zA-Z0-9]*[^/]')(jc/parsers/ip_address.py)先把%后的内容剥离并暂存,解析成功后再回填到scope_id字段:

scope_match = re.search(SCOPE_PATTERN, data) if scope_match: scope_string = scope_match.group(0)[1:] data = re.sub(SCOPE_PATTERN, '', data)

掩码字段的跨版本兼容

由于旧版 Python(如 3.6)在输入为十进制整数时不提供hostmask/netmask,源码通过try/except AttributeError手工兜底(jc/parsers/ip_address.py):IPv4 回退为0.0.0.0/255.255.255.255,IPv6 回退为::/ 全ffff。

/31、/32、/127、/128 的特殊处理

普通网段的主机范围是"网络地址 + 1"到"广播地址 - 1",但对点对点链路使用的极端前缀,源码(jc/parsers/ip_address.py)做了专门分支:

  • /31(IPv4)与/127(IPv6):first_host与last_host直接用网络地址和广播地址,hosts为 2;
  • /32(IPv4)与/128(IPv6):first_host与last_host都等于地址本身,hosts为 1。

int / hex / bin 的生成

  • int:直接对ipaddress对象调用int();
  • hex:借助辅助函数_b2a()(jc/parsers/ip_address.py)把.packed字节串用binascii.hexlify(byte_string, ':')转成冒号分隔的十六进制;为了兼容 Python 3.6/3.7(separator参数 3.8 才引入),还保留了手写两两分组的回退分支;
  • bin:由_bin_format()(jc/parsers/ip_address.py)通过format(int(ip), '0>' + str(length) + 'b')生成指定位数的二进制串(IPv4 32 位、IPv6 128 位)。

整个解析器在parse()最后以raw_output if raw else _process(raw_output)返回,其中_process()目前是直接透传,说明该解析器默认输出的即为符合 Schema 的结构化数据。

测试验证与边界覆盖

仓库中的 tests/test_ip_address.py 为解析器提供了完整的单元测试,覆盖了以下场景:

  • 空输入返回{}(test_ip_address_nodata);
  • 纯 IPv4、IPv4+CIDR、IPv4 点分掩码、IPv4 整数记法;
  • 纯 IPv6、IPv6+CIDR、IPv6+CIDR+Scope ID、IPv6 整数记法;
  • IPv4 映射地址(::FFFF:192.168.1.35,同时兼容新旧两种 Python 行为);
  • 6to4 地址(2002:c000:204::/48)与 Teredo 地址(2001:0000:4136:e378:8000:63bf:3fff:fdd2)。

其中 IPv4 映射与 6to4 的测试特意设计了"新旧风格均可通过"的容错断言,以兼容不同 Python 版本对is_reserved、is_private等分类标志的判定差异——这也是文档示例中个别布尔值与不同 Python 版本输出可能略有出入的原因。

进阶用法:与 --slurp 组合批量解析

由于解析器带有slurpable标签,可以配合--slurp选项将多行地址一次性转换为 JSON 数组:

$ printf '192.168.1.1\n192.168.2.10/24\n' | jc --ip-address --slurp -p

这在批量审计、巡检脚本中非常实用:结合jq可以按is_private、cidr_netmask等字段快速过滤地址清单。更完整的 jc 使用方式可参考 docs/readme.md 与 EXAMPLES.md。

小结

jc --ip-address把"IP 地址字符串"这一常见数据形态,一次性扩展为包含网络规划、地址分类、多进制表示的完整结构化 JSON。其实现完全基于 Python 标准库ipaddress,并针对旧版 Python 的scope_id、hostmask、netmask缺失做了兼容兜底,对/31、/32、/127、/128等极端前缀也有专门处理。无论你是用它做脚本里的地址解析,还是配合--slurp与jq做批量地址审计,本文给出的 Schema 对照与示例都能直接作为参考。

  • 开发工具

【免费下载链接】jc

CLI tool and python library that converts the output of popular command-line tools, file-types, and common strings to JSON, YAML, or Dictionaries. This allows piping of output to tools like jq and simplifying automation scripts.

项目地址:https://gitcode.com/gh_mirrors/jc/jc
点击查看免费下载
上一篇:揭秘Calibre-Web自更新机制:如何保留配置和数据库安全升级
下一篇:Roc 语言 REPL 闭包求值实战:以 simple_string_closure 快照测试为例解析函数式求值管线

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询