Shell sed括号表达式和捕获组

Shell sed括号表达式和捕获组,shell,awk,sed,Shell,Awk,Sed,我有以下需要通过sed处理的字符串集: start-pattern [SYSTEM] capture ............................... FAIL [ 2.825 s] [SYSTEM] capture ............................... FAIL [ 2.825 s] [DEBUG] capture :: capture :: capture .......... FAIL [ 0.866 s] [DEBUG] capture ::

我有以下需要通过sed处理的字符串集:

start-pattern
[SYSTEM] capture ............................... FAIL [  2.825 s]
[SYSTEM] capture ............................... FAIL [  2.825 s]
[DEBUG] capture :: capture :: capture .......... FAIL [  0.866 s]
[DEBUG] capture :: me :: capture capture capture FAIL [  0.876 s]
[DEBUG] capture-me ............................. FAIL [  0.361 s]
end-pattern
我想为失败的测试用例的每一行编写一个sed表达式(如果可能的话,最好使用sed)来获取
[DEBUG]
|
[SYSTEM]
失败[.*]
之间以及文本{start,end}模式之间的所有字符串

上述文本的输出应为以下一项或多项:

capture
capture
capture::capture::capture
capture::me::capture capture capture
capture-me
$ gsed -nE 's/\[(DEBUG|SYSTEM)\] (.*) FAIL.*/\2/;{s/[.]//g;s/ :: /::/g;p;}' file                                                                                                                                                            
capture 
capture 
capture::capture::capture 
capture::me::capture capture capture
capture-me 
以下是我尝试过的,但并不适用于所有行:

sed -e 's/\[DEBUG\] \(.*\) :: \(.*\) :: \(.*\) \([^.]FAIL \[.*\]) \[.*/\1::\2::\3::\4/' -e 's/\[SYSTEM\] \(.*\) \..*/\1/'

您可以使用以下选项:

capture
capture
capture::capture::capture
capture::me::capture capture capture
capture-me
$ gsed -nE 's/\[(DEBUG|SYSTEM)\] (.*) FAIL.*/\2/;{s/[.]//g;s/ :: /::/g;p;}' file                                                                                                                                                            
capture 
capture 
capture::capture::capture 
capture::me::capture capture capture
capture-me 

-n
选项自动停止
sed
打印行,并且
-E
打开扩展正则表达式(此选项在GNU sed中记录为-r,但
-E
同时适用于GNU和BSD sed)


这对我来说适用于示例输入:

sed -nE '/^.*\[(SYSTEM|DEBUG)\] *(.*[^ ]) *FAIL.*$/{;s//\2/;s/[.]//g;p;}'
  • -n
    说“不要打印每一行”
  • -E
    打开扩展正则表达式(与
    |
    交替使用时需要它,如果没有它,即使作为
    \\\124;
    也不可用)
  • /^.\[(系统调试)\]*(.[^])*失败。*$/
    匹配我们要查找的所有行
  • {
    开始一块分号分隔的命令,以应用于匹配行
  • s//\2/
    说用第二组
    )之间匹配的部分替换与先前正则表达式匹配的部分。
  • s/[.]//g
    删除所有句点
  • p
    打印出该行
  • }
    终止块

  • 这也起到了作用:

    sed -n -e '/^\[SYSTEM\]/ ba; /^\[DEBUG\]/ ba; b;'
           -e ':a s/^\[.*\]\(.*\)FAIL.*/\1/; s/[ \.]*//g; \
               :c s/\(capture\)\(capture\)/\1 \2/g; tc; p;'
    testcases.txt
    
    产出:

    capture
    capture
    capture::capture::capture
    capture::me::capture capture capture
    capture-me
    
    如果行以
    [SYSTEM]
    [DEBUG]
    开头,则执行分支并进行替换,并打印结果。否则什么也不做

    由于需求(在问题描述中没有提到,但由期望的输出隐式给出)存在另一种结构,它在两个连续捕获之间保持空白

    更详细地说:

    1.
    -n
    :如果没有通过
    p
    命令明确强制,则不要打印图案空间

    2.
    ba
    :跳到标签
    a

    3.
    b
    :跳到脚本末尾


    4.
    tc
    :如果成功地进行了替换(自读入最后一行以及自上次使用
    t
    t
    ),则跳到标签
    c

    使用以下
    sed
    命令组合:

    sed -En 's/^\[(DEBUG|SYSTEM)\] (.+) FAIL.*$/\2/p' testfile | sed -En 's/(\.|\s(::)\s)/\2/gp'
    
    输出:

    capture 
    capture 
    capture::capture::capture 
    capture::me::capture capture capture
    capture-me 
    
    第二个命令
    s/(\.\s(:)\s)/\2/gp
    将删除所有点
    ,并用其修剪值替换
    :'


    缩短的版本如下所示:

    sed -En 's/^\[(DEBUG|SYSTEM)\] (.+) FAIL.*$/\2/;s/(\.|\s(::)\s)/\2/gp' testfile
    

    以下是如何在任何UNIX系统上清晰、简单、可靠、高效和可移植地完成您的要求:

    $ cat tst.awk
    /start-pattern/ { inBlock=1 }
    inBlock {
        if ( sub(/^\[(DEBUG|SYSTEM)\]/,"") && sub(/FAIL.*/,"") ) {
            gsub(/[[:space:].]/,"")
            print
        }
    }
    /end-pattern/ { inBlock=0 }
    
    $ awk -f tst.awk file
    capture
    capture
    capture::capture::capture
    capture::me::capturecapturecapture
    capture-me
    

    请注意,您说过希望输出
    不包括空格和句点。
    因此上面的“捕获”之间没有空格。如果您真正想要的只是排除
    s周围以及输出行的开始/结束处的空格,那么这只是一个调整:

    $ cat tst.awk
    /start-pattern/ { inBlock=1 }
    inBlock {
        if ( sub(/^\[(DEBUG|SYSTEM)\]/,"") && sub(/FAIL.*/,"") ) {
            gsub(/[[:space:]]*::[[:space:]]*/,"::")
            gsub(/^[[:space:]]+|[[:space:]]+$|[.]/,"")
            print
        }
    }
    /end-pattern/ { inBlock=0 }
    
    $ awk -f tst.awk file
    capture
    capture
    capture::capture::capture
    capture::me::capture capture capture
    capture-me
    


    @MarkReed不确定它是什么时候引入的,但据我记忆所及,它一直是一个未记录的支持选项。不幸的是,当我使用-ne或-nE@askb您能否仅在示例输入上运行它,并告诉我是否出现错误?查看它在linux上使用的GNU上的工作情况此处@askb该行是以
    [DEBUG]
    开头还是前面有空格?@askb try updated命令,它应该产生您所需要的输出。除了
    capture::me::capturecapturecapture
    应该是
    capture::me::capture
    之外,其余的行都可以正常工作,所以您希望保留内部空间。检查编辑的答案。对问题做了一个小的修改,我需要处理开始和结束模式之间的所有行对问题做了一个小的修改,我需要处理开始和结束模式之间的所有行显示那些
    开始模式
    结束模式
    看起来像什么?他们的实际价值是什么?抱歉!这些是确切的关键字而不是模式它们的确切名称是
    开始模式
    结束模式
    ,字面意思是?您不能接受Perl单行程序吗?非常简短。我对这个问题做了一个小小的修改,我需要处理开始和结束模式之间的所有行。第4行不是一个匹配项。它是一个匹配项,用于输出排除空格。我添加了一个版本,可以生成发布的预期输出,以防这是真正需要的,而不是错误。谢谢,我明天会尝试。。你能解释一下排除空格和句号的更多信息吗。我想排除的内容是从要求的文本中的,而不是从要求的文本中。你也可以看看这个问题,我想知道谁应该在awk中这样做:谢谢,我错过了。