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

Bash正则表达式与Grep使用遇阻,寻求技术协助

问题:使用grep提取Scenario测试块时意外包含注释占位符

我正在编写Bash脚本,需要从以下文本中提取所有Scenario测试块:

#
  #------------------------------------------- spaceholder ---------------------------------------------------------------------------
  #

  #@E2E-1 @id:1 
  Scenario: Login & Search: B2B_PKG_IN >> BE
    Given I am on the login page
    When I enter <username> and incorrect password multiple times
    Then I should be locked out of my account
    And I should see a lockout message



  #@E2E-2 @id:32 
  Scenario: Login & Search: B2B_PKG_IN >> NL
    Given I am on the login page
    When I enter <username> and incorrect password multiple times
    Then I should be locked out of my account
    And I should see a lockout message


  #
  #------------------------------------------- B2B_PKG_3PA ---------------------------------------------------------------------------


  #

  @E2E-3 @id:3
  Scenario: Login & Search: B2B_PKG_3PA >> BE
    Given I am on the login page
    When I enter <username> and incorrect password multiple times
    Then I should be locked out of my account
    And I should see a lockout message

我用正则表达式((@[^\n]+|#@[^\n]+)?\s*)?Scenario:[^\n]*\n(?:[^\n]*\n)*?\n在在线正则测试工具中可以正确提取目标块,但执行grep -Pzo "$pattern" "$current_file"时,结果意外包含了开头的#------------------------------------------- spaceholder ...注释部分。尝试过grep -E、grep -oP、grep -Po等参数组合都无法解决。


原因分析

grep -z会将整个文件读取为单个NUL分隔的记录,原正则中的非贪婪匹配(?:[^\n]*\n)*?在这种模式下,可能因为注释块的连续换行触发意外匹配;同时原正则未明确排除纯注释行(不含#@的注释),导致grep从注释块开始匹配到后续的Scenario块。

修正后的解决方案

方案1:调整正则,明确匹配规则

使用更精确的正则,确保只匹配带有可选标签(@xxx或#@xxx)的Scenario块,且跳过纯注释行:

pattern='(^\s*(#@|@)[^\n]+\s*)?^\s*Scenario:[^\n]*\n(?:^\s+[^\n]+\n)*'
grep -Pzo "$pattern" "$current_file" | tr '\0' '\n'

正则解释:

  • (^\s*(#@|@)[^\n]+\s*)?:匹配可选的标签行(以#@或@开头,允许前导空格),?表示该标签行非必需
  • ^\s*Scenario:[^\n]*\n:匹配Scenario行,允许前导空格
  • (?:^\s+[^\n]+\n)*:匹配后续的步骤行(必须有前导空格,确保是Scenario的子步骤),重复匹配所有步骤行

参数说明:

  • -P:启用Perl兼容正则表达式
  • -z:将文件视为NUL分隔的记录,支持跨行匹配
  • -o:只输出匹配的部分
  • tr '\0' '\n':将grep输出的NUL字符转换回换行,恢复正常文本格式

方案2:使用awk替代grep(更直观稳定)

如果正则在grep中容易出问题,用awk处理结构化文本更可靠:

awk '/^\s*(#@|@)/{tag=$0; next} /^\s*Scenario:/{if(tag!="")print tag; print; in_scenario=1; next} in_scenario && /^\s+/{print} in_scenario && /^\s*$/{in_scenario=0; print ""}' "$current_file"

逻辑解释:

  1. 匹配标签行(#@或@开头),保存标签内容并跳过后续处理
  2. 匹配Scenario行,打印标签(如果存在)和Scenario行,标记进入Scenario块
  3. 在Scenario块内,匹配有前导空格的步骤行并打印
  4. 遇到空行时,退出Scenario块并打印空行分隔不同测试块

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:22:32