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

SED提取*SET_PART开头段落异常:如何实现精准连续匹配

提取特定段落的文本处理需求与解决方案建议

需求说明

需要提取文本中所有以*SET_PART开头的段落,段落的结束标志是下一个以*开头的行(该*行是新段落的起始,不应包含在当前段落中,且要作为下一次搜索的起始点)。

当前使用的命令:

sed -n '/*SET_PART/,/*/p' Inputfile > Outputfile

输入文件(Inputfile)内容

*SET_PART_COLLECT_TITLE
    Gesamtfahrzeug
           101                                        
       1005043   1005049   1005101   1005102   1005103   1005200   1005300   1005400
       1005504   1005601   1005700   1005800   1005900   1006000   1006100   1006101
       1006102   1006103   1006200   1006201   1006202   1006203   1006400   1006401
       1006402   1006500   1006600   1006700   1006800   1006900   1007000   1007100
       1007200   1007201   1007202   1007203   1007204   1007300   1007301   1007302
       1007303   1007304   1007305   1007306   1007307   1007308   1007309   1007310
       1007311   1007312   1007313   1007314   1007400   1007500   1007600   1007700
       1007800   1007801   1015700   1015800
    *Keyword
           202                                        
       1000000   1002002   1002312   1002313   1002323   1002701
    
    
    *SET_PART_COLLECT_TITLE
    Verbindungstechnik_Slave
           201                                        
       1000000   1002002   1002312   1002313   1002323   1002701
    *SET_PART_LIST_TITLE
    Bord_stein_hi_Forcetransducer
             3        0.        0.        0.        0.
             3
    *SET_PART_COLLECT_TITLE
    *SET_PART_LIST_TITLE
    Fahrbahn_Forcetransducer
             1                                        
             1
    *END

当前命令的输出问题

执行上述命令后,会错误地包含结束标志行(比如*Keyword),且无法正确处理连续的*SET_PART段落,输出如下:

*SET_PART_COLLECT_TITLE
    Gesamtfahrzeug
           101                                        
       1005043   1005049   1005101   1005102   1005103   1005200   1005300   1005400
       1005504   1005601   1005700   1005800   1005900   1006000   1006100   1006101
       1006102   1006103   1006200   1006201   1006202   1006203   1006400   1006401
       1006402   1006500   1006600   1006700   1006800   1006900   1007000   1007100
       1007200   1007201   1007202   1007203   1007204   1007300   1007301   1007302
       1007303   1007304   1007305   1007306   1007307   1007308   1007309   1007310
       1007311   1007312   1007313   1007314   1007400   1007500   1007600   1007700
       1007800   1007801   1015700   1015800
    *Keyword
    *SET_PART_COLLECT_TITLE
    Verbindungstechnik_Slave
           201                                        
       1000000   1002002   1002312   1002313   1002323   1002701
    *SET_PART_LIST_TITLE
    *SET_PART_COLLECT_TITLE
    *SET_PART_LIST_TITLE

期望输出

准确提取所有*SET_PART开头的段落,不包含后续的非*SET_PART起始行,且连续的*SET_PART段落都能被正确提取:

*SET_PART_COLLECT_TITLE
    Gesamtfahrzeug
           101                                        
       1005043   1005049   1005101   1005102   1005103   1005200   1005300   1005400
       1005504   1005601   1005700   1005800   1005900   1006000   1006100   1006101
       1006102   1006103   1006200   1006201   1006202   1006203   1006400   1006401
       1006402   1006500   1006600   1006700   1006800   1006900   1007000   1007100
       1007200   1007201   1007202   1007203   1007204   1007300   1007301   1007302
       1007303   1007304   1007305   1007306   1007307   1007308   1007309   1007310
       1007311   1007312   1007313   1007314   1007400   1007500   1007600   1007700
       1007800   1007801   1015700   1015800
    *SET_PART_COLLECT_TITLE
    Verbindungstechnik_Slave
           201                                        
       1000000   1002002   1002312   1002313   1002323   1002701
    *SET_PART_LIST_TITLE
    Bord_stein_hi_Forcetransducer
             3        0.        0.        0.        0.
             3
    *SET_PART_COLLECT_TITLE
    *SET_PART_LIST_TITLE
    Fahrbahn_Forcetransducer
             1                                        
             1

解决方案

改进的sed命令

利用sed的分支和标记功能实现需求,避免包含结束行,并支持连续段落:

sed -n '/\*SET_PART/{:a;N;/\n\*/{s/\n\*.*//;p;b};ba}' Inputfile > Outputfile

解释:

  • /\*SET_PART/:匹配到*SET_PART行时进入处理流程
  • :a:定义循环标记a
  • N:读取下一行到模式空间
  • /\n\*/:检查是否遇到以*开头的行
    • 匹配成功:删除该*行及其换行符,打印结果后跳出循环
    • 匹配失败:跳回标记a继续读取下一行

更合适的工具:awk

awk的段落处理逻辑更直观,代码可读性更强:

awk '/^\*/ {
    if (in_part) {
        print buffer
        buffer = ""
    }
    if ($0 ~ /\*SET_PART/) {
        in_part = 1
        buffer = $0 "\n"
    } else {
        in_part = 0
    }
    next
}
in_part { buffer = buffer $0 "\n" }
END { if (in_part) print buffer }' Inputfile > Outputfile

解释:

  • 遇到以*开头的行时:
    • 如果正在处理*SET_PART段落,先打印之前缓存的内容
    • 判断当前行是否是*SET_PART开头,是则开启处理标记并缓存该行,否则关闭标记
  • 开启处理标记时,将每行内容加入缓存
  • 文件处理结束时,打印剩余的缓存内容

环境说明

使用的Gnome版本为3.32.2,上述工具(sed、awk)均为Linux系统默认自带工具,无需额外安装。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:10:28