Shell sed括号表达式和捕获组
我有以下需要通过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 ::
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中这样做:谢谢,我错过了。