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

如何用grep优雅处理匹配大括号的文本内容提取?

文本格式转换方案

输入文本

VARA {APPLE}
VARB {
          ORANGE
          BANANA
     }
VARC {
          KIWI{0}
          KIWI{1}
          BERRY
     }
VARD {CHERRY{0} MELON}

期望输出

VARA APPLE
VARB ORANGE BANANA
VARC KIWI{0} KIWI{1} BERRY
VARD CHERRY{0} MELON

仅用grep的可行性

纯grep无法实现需求。grep仅擅长单模式行匹配与提取,没法处理跨多行的大括号配对逻辑,也无法识别嵌套括号(如KIWI{0})的层级关系并保留对应内容,必须借助支持状态跟踪的工具。

优雅替代方案:awk脚本

awk可以通过跟踪括号嵌套层级,将同一变量对应的多行内容合并为一行,同时保留嵌套括号的内容。脚本逻辑如下:

  • 初始化括号深度depth=0、当前变量名var、内容缓冲区content
  • 逐行处理文本,先去除行首尾空格
  • 按字符位置优先处理{或}:
    • 遇到外层{时提取变量名,遇到嵌套{直接保留字符并增加深度
    • 遇到外层}时输出变量名+整理后的内容,遇到嵌套}直接保留字符并减少深度
    • 非括号字符在括号内时,自动合并连续空格为单个空格

完整awk脚本

BEGIN { depth=0; var=""; content="" }
{
    gsub(/^[[:space:]]+|[[:space:]]+$/, "")
    line = $0
    while (length(line) > 0) {
        if (index(line, "{") < index(line, "}") || index(line, "}") == 0) {
            pos = index(line, "{")
            if (pos > 0) {
                if (depth == 0) {
                    var = substr(line, 1, pos-1)
                    gsub(/[[:space:]]+$/, "", var)
                    line = substr(line, pos+1)
                } else {
                    content = content " " substr(line, 1, pos)
                    line = substr(line, pos+1)
                }
                depth++
            } else {
                content = content " " line
                line = ""
            }
        } else {
            pos = index(line, "}")
            depth--
            if (depth == 0) {
                content = content " " substr(line, 1, pos-1)
                gsub(/^[[:space:]]+|[[:space:]]+$/, "", content)
                print var " " content
                var = ""
                content = ""
                line = substr(line, pos+1)
            } else {
                content = content " " substr(line, 1, pos)
                line = substr(line, pos+1)
            }
        }
    }
}

使用方法

将脚本保存为process.awk,执行命令:

awk -f process.awk 你的输入文件名.txt

备选:Shell逐字符处理脚本

如果偏好纯shell实现,也可以通过逐字符读取并跟踪括号深度来完成,逻辑和awk一致:

#!/bin/bash
input="$1"
depth=0
var=""
content=""
while IFS= read -r -n1 char; do
    if [[ "$char" == "{" ]]; then
        ((depth++))
        if [[ $depth -eq 1 ]]; then
            var=$(echo "$var" | sed 's/[[:space:]]*$//')
        else
            content+="$char"
        fi
    elif [[ "$char" == "}" ]]; then
        ((depth--))
        if [[ $depth -eq 0 ]]; then
            content=$(echo "$content" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
            echo "$var $content"
            var=""
            content=""
        else
            content+="$char"
        fi
    elif [[ $depth -eq 0 ]]; then
        var+="$char"
    else
        if [[ "$char" =~ [[:space:]] ]]; then
            if [[ "${content: -1}" != " " ]]; then
                content+=" "
            fi
        else
            content+="$char"
        fi
    fi
done < "$input"

使用方法

将脚本保存为process.sh,赋予执行权限后执行:

chmod +x process.sh
./process.sh 你的输入文件名.txt

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:32:14