- 开发工具
【免费下载链接】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.
本指南深入讲解 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| 参数 | 类型 | 说明 |
|---|---|---|
data | string | 待解析的地址文本(IPv4/IPv6,可含 CIDR、Scope ID,或直接是整数记法) |
raw | boolean | 为True时返回未处理的原始结构化数据 |
quiet | boolean | 为True时抑制警告信息(如平台兼容性提示) |
函数内部会先调用jc.utils.compatibility()校验平台兼容性、用jc.utils.input_type_check()检查输入类型,再进入正式的解析逻辑。
支持的输入格式
根据文档说明,该解析器接受标准记法与整数记法两种形式的 IPv4/IPv6 地址,标准记法还可以附加 CIDR 子网掩码与 Scope ID:
| 输入形式 | 示例 | 说明 |
|---|---|---|
| IPv4 标准地址 | 192.168.1.1 | 点分十进制 |
| IPv4 带 CIDR | 192.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 带 CIDR | 127:0:de::1/96 | |
| IPv6 带 Scope ID | 127: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. 版本与地址形态
| 字段 | 类型 | 说明 |
|---|---|---|
version | integer | IP 版本号,IPv4 为 4,IPv6 为 6 |
max_prefix_length | integer | 最大前缀长度,IPv4 为 32,IPv6 为 128 |
ip | string | 规范化后的裸地址(不带 CIDR) |
ip_compressed | string | 压缩写法(IPv6 用::折叠连续零段) |
ip_exploded | string | 展开写法(IPv6 每段补足 4 位十六进制) |
ip_split | array[string] | 按段拆分的地址列表:IPv4 为 4 个十进制数,IPv6 为 8 个四位十六进制段 |
scope_id | string/null | IPv6 接口 Scope ID,无则为null |
ipv4_mapped | string/null | IPv4 映射地址(::ffff:x.x.x.x)中还原出的 IPv4,无则为null |
six_to_four | string/null | 6to4 地址(2002::/16)中内嵌的 IPv4,无则为null |
teredo_client | string/null | Teredo 地址中的客户端 IPv4,无则为null |
teredo_server | string/null | Teredo 地址中的服务器 IPv4,无则为null |
2. 网络与主机范围
| 字段 | 类型 | 说明 |
|---|---|---|
dns_ptr | string | 反向 DNS PTR 记录名(IPv4 为in-addr.arpa,IPv6 为ip6.arpa) |
network | string | 网络地址 |
broadcast | string | 广播地址 |
hostmask | string | 主机掩码(与子网掩码互补) |
netmask | string | 子网掩码 |
cidr_netmask | integer | CIDR 前缀长度(如/24为 24) |
hosts | integer | 可用主机数(不含网络地址与广播地址) |
first_host | string | 第一个可用主机地址 |
last_host | string | 最后一个可用主机地址 |
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 -pscope_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 -pipv4_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 # Teredo6to4 示例的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.
相关推荐
jc 将 /proc/net/if_inet6 转为结构化 JSON:解析 Linux 网络接口 IPv6 地址表的实战指南
jc 将 /proc/net/if_inet6 转为结构化 JSON:解析 Linux 网络接口 IPv6 地址表的实战指南 Linux 内核通过 /proc/
开发工具fastfetch 内置的 Shell 补全脚本怎么用?为 bash/zsh/fish 启用 tab 补全
fastfetch 内置的 Shell 补全脚本怎么用?为 bash/zsh/fish 启用 tab 补全 fastfetch 仓库自带三份 shell 补全脚
开发工具jc proc-cpuinfo 解析器:将 Linux /proc/cpuinfo 精准转换为结构化 JSON
jc proc cpuinfo 解析器:将 Linux /proc/cpuinfo 精准转换为结构化 JSON 本文基于 proc_cpuinfo 解析器文档
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考