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

如何在Bash中循环遍历多个正则表达式匹配结果

解决Bash中用正则循环提取多个捕获组数据的问题

我明白你的需求——要从这个包含多个JSON对象的字符串里,用正则提取每条数据的id、name和address,还要循环遍历所有匹配结果。你现在的代码只能拿到第一个匹配项,因为Bash的=~运算符默认只会执行一次匹配,咱们得调整一下逻辑来实现循环遍历。

方法一:纯Bash内置循环(无需额外工具)

先修正一下你的正则表达式(补上遗漏的闭合引号,避免匹配出错),然后通过每次匹配后截断字符串的方式,循环处理所有条目:

#!/bin/bash
string=' { "id" : 45, "name" : "John Doe", "address" : "123 Fake Street" }, { "id" : 46, "name" : "Jane Doe", "address" : "234 Somewhere Road" } '
# 修正后的正则:补上了name和address值后面的闭合引号,确保匹配准确
regex='\{[^\}]*id" : ([0-9]*)[^\}]*name" : "([a-zA-Z ]*)"[^\}]*address" : "([a-zA-Z0-9 ]*)"[^\}]*\}'

# 循环匹配所有条目
while [[ "$string" =~ $regex ]]; do
    # 从BASH_REMATCH数组中提取捕获组内容
    id="${BASH_REMATCH[1]}"
    name="${BASH_REMATCH[2]}"
    address="${BASH_REMATCH[3]}"
    
    # 输出当前条目的数据(你可以换成自己的处理逻辑)
    echo "找到条目:ID=$id,姓名=$name,地址=$address"
    
    # 截断字符串:去掉已经处理过的匹配内容,继续处理剩余部分
    string="${string#*"${BASH_REMATCH[0]}"}"
done

工作原理:

  1. 每次循环用=~匹配当前字符串中的第一个条目;
  2. BASH_REMATCH[0]是整个匹配的内容,BASH_REMATCH[1]/[2]/[3]对应你定义的三个捕获组;
  3. 用${string#*匹配内容}把字符串中匹配部分及之前的内容删除,剩下的字符串进入下一轮循环,直到没有匹配项为止。

方法二:先提取单个对象再逐个处理(更清晰)

如果字符串结构更复杂,纯Bash的截断可能容易出错,咱们可以先用grep把每个独立的{...}对象提取出来,再逐个用正则解析:

#!/bin/bash
string=' { "id" : 45, "name" : "John Doe", "address" : "123 Fake Street" }, { "id" : 46, "name" : "Jane Doe", "address" : "234 Somewhere Road" } '

# 用grep提取每个独立的JSON对象(-o只输出匹配部分,-P启用Perl兼容正则)
while read -r obj; do
    # 对单个对象应用正则提取数据
    if [[ "$obj" =~ id" : ([0-9]*).*name" : "([a-zA-Z ]*)".*address" : "([a-zA-Z0-9 ]*)" ]]; then
        echo "找到条目:ID=${BASH_REMATCH[1]},姓名=${BASH_REMATCH[2]},地址=${BASH_REMATCH[3]}"
    fi
done < <(grep -oP '\{[^\}]+\}' <<< "$string")

这个方法把“提取所有对象”和“解析单个对象”分开,逻辑更清晰,也更容易维护。

额外推荐:用专业工具处理JSON(更可靠)

虽然你问的是正则,但还是要提一句:如果你的字符串是标准JSON格式,用jq工具处理会比正则靠谱得多——正则处理JSON很容易因为值里的特殊字符(比如引号、转义符)出问题。用jq的示例代码:

#!/bin/bash
string=' [ { "id" : 45, "name" : "John Doe", "address" : "123 Fake Street" }, { "id" : 46, "name" : "Jane Doe", "address" : "234 Somewhere Road" } ] '

# 先把字符串转成合法的JSON数组(如果原来不是的话),再用jq遍历
echo "$string" | jq -c '.[]' | while read -r item; do
    id=$(jq -r '.id' <<< "$item")
    name=$(jq -r '.name' <<< "$item")
    address=$(jq -r '.address' <<< "$item")
    echo "找到条目:ID=$id,姓名=$name,地址=$address"
done

jq是专门处理JSON的工具,能完美处理各种边缘情况,建议优先考虑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:51:34