You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本中匹配特定字符间内容的正则失效问题排查

Kubectl镜像列表处理:sed/awk正则无效的原因及解决办法

问题背景

我需要清理Kubectl导出的Pod镜像列表内容,删除不必要字符。首先通过以下命令获取Pod镜像列表并保存到temp文件:

kubectl get pods -n $1 -o jsonpath='{range .items[*]}{@.spec.containers[*].image}{","}{@.status.containerStatuses[*].imageID}{"\n"}{end}'

尝试用sed删除逗号(,)到@之间的所有字符(含@),在Regex101中验证有效的正则,在shell中执行却无效果:

sed -i 's/(?<=\,)(.*?)(?<=\@)//g' temp

改用awk命令也未得到预期结果:

awk '!/(?<=\,)(.*?)(?<=\@)/' temp

示例输入

docker.elastic.co/elasticsearch/elasticsearch:7.17.5,docker-pullable://docker.elastic.co/elasticsearch/elasticsearch@sha256:76344d5f89b13147743db0487eb76b03a7f9f0cd55abe8ab887069711f2ee27d
docker.io/bitnami/kafka:3.3.1-debian-11-r11,docker-pullable://bitnami/kafka@sha256:be29db0e37b6ab13df5fc14988a4aa64ee772c7f28b4b57898015cf7435ff662
docker.io/bitnami/mongodb:6.0.3-debian-11-r0,docker-pullable://bitnami/mongodb@sha256:e7438d7964481c0bcfcc8f31bca2d73022c0b7ba883143091a71ae01be6d9edb
docker.io/bitnami/postgresql:14.1.0-debian-10-r80,docker-pullable://bitnami/postgresql@sha256:6eb9c4ab3444e395df159e2cad21f283e4bf30802958467590c886f376dc9959
docker.io/bitnami/zookeeper:3.8.0-debian-11-r47,docker-pullable://bitnami/zookeeper@sha256:0f3169499c5ee02386c3cb262b2a0d3728998d9f0a94130a8161e389f61d1462

预期输出

docker.elastic.co/elasticsearch/elasticsearch:7.17.5,sha256:76344d5f89b13147743db0487eb76b03a7f9f0cd55abe8ab887069711f2ee27d
docker.io/bitnami/kafka:3.3.1-debian-11-r11,sha256:be29db0e37b6ab13df5fc14988a4aa64ee772c7f28b4b57898015cf7435ff662
docker.io/bitnami/mongodb:6.0.3-debian-11-r0,sha256:e7438d7964481c0bcfcc8f31bca2d73022c0b7ba883143091a71ae01be6d9edb
docker.io/bitnami/postgresql:14.1.0-debian-10-r80,sha256:6eb9c4ab3444e395df159e2cad21f283e4bf30802958467590c886f376dc9959
docker.io/bitnami/zookeeper:3.8.0-debian-11-r47,sha256:0f3169499c5ee02386c3cb262b2a0d3728998d9f0a94130a8161e389f61d1462

请问是哪里出错了,还是Unix/shell中的正则规则不同?


原因分析

  1. sed正则语法不兼容:sed默认使用基本正则表达式(BRE),即使添加-r参数启用扩展正则表达式(ERE),也不支持PCRE(Perl兼容正则表达式)中的正向预查(?<=...)这类零宽断言语法。你在Regex101中用的是PCRE规则,但shell里的sed不支持,导致匹配失败,没有替换效果。
  2. sed正则逻辑错误:你的正则试图通过预查定位要删除的内容,但sed的替换是需要直接匹配到目标内容才能替换,这种预查的写法不符合sed的工作逻辑。
  3. awk命令逻辑错误:awk '!/.../'是用来过滤不匹配正则的行,而不是替换行内的内容。同时awk默认也不支持PCRE的正向预查语法,所以这条命令完全达不到修改内容的目的。

解决办法

方法1:使用sed简化正则

直接匹配逗号到@之间的所有内容,替换为单个逗号,语法简单且兼容所有sed版本:

sed -i 's/,.*@/,/' temp

解释:,.*@匹配从逗号开始到最后一个@的所有字符(sed默认是贪婪匹配,正好覆盖你要删除的部分),替换为,后,就保留了逗号前的镜像名和@后的sha256值。

方法2:使用awk处理

通过分割字符串实现,逻辑清晰:

awk -F '@' '{split($1, arr, ","); print arr[1] "," $2}' temp

解释:

  • 用@作为分隔符,将每行分成两部分,$2就是sha256开头的部分
  • 再将第一部分$1用逗号分割,arr[1]就是镜像名
  • 最后拼接镜像名+逗号+$2得到预期结果

内容的提问来源于stack exchange,提问作者airen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:45:40