sed括号表达式和捕获组

时间:2017-02-25 12:57:49

标签: 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 :: me :: capture capture capture FAIL [  0.876 s]
[DEBUG] capture-me ............................. FAIL [  0.361 s]
end-pattern

我想写一个sed表达式(如果可能的话,最好使用sed)来获取[DEBUG] ||之间的所有字符串失败的测试用例的每一行都有[SYSTEM]FAIL [.*],文本{start,end} -pattern之间的空格和句点.除外。

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

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/'

6 个答案:

答案 0 :(得分:3)

以下是如何在任何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

请注意,您说您想要输出excluding spaces and period .,因此上面的" capture"之间没有空格。如果您真正想要的只是排除::周围的空格以及输出行的开头/结尾,那么这只是一个调整:

$ 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

答案 1 :(得分:1)

您可以使用以下内容:

$ 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启用扩展正则表达式(此选项记录为-r with GNU sed -E适用于GNU和BSD sed)

s              # Substitution command
/              # Start of match
\[             # Match a literal [
(DEBUG|SYSTEM) # Match DEBUG OR SYSTEM
\]             # Match a literal ] followed by a space
(.*)           # Match everything after and capture it
 FAIL.*        # Match a FAIL and everything after
/              # Stop match and start replacement
\2             # Replace with the second capture group
{              # If substitution matched applied following commands
s/[.]//g;      # Global substitution of literal .
s/ :: /::/g;   # Global substitution of spaces around literal ::
p;             # Print the result
}   

答案 2 :(得分:1)

这对我来说对样本输入有用:

data FixMePls a = FixMe | Pls a deriving (Eq, Show)

instance Monoid a => Monoid (FixMePls a) where
  mempty = Nothing
  mappend m Nothing = m
  mappend Nothing m = m
  mappend (Pls a) (Pls a') = Pls (mappend a a')

instance Applicative FixMePls where
  pure = Pls
  Nothing <*> _ = Nothing
  _ <*> Nothing = Nothing
  Pls f <*> Pls a = Pls f a


main :: IO ()
main = do
  putStrLn("Weee!!!1!")
  1. sed -nE '/^.*\[(SYSTEM|DEBUG)\] *(.*[^ ]) *FAIL.*$/{;s//\2/;s/[.]//g;p;}' 说&#34;不要打印每一行&#34;
  2. -n启用扩展正则表达式(与-E交替时需要;没有它,即使|也不可用)
  3. \|匹配我们正在寻找的每一行的所有
  4. /^.*\[(SYSTEM|DEBUG)\] *(.*[^ ]) *FAIL.*$/开始一系列以分号分隔的命令以应用于匹配行
  5. {表示要替换与前一个正则表达式匹配的内容,只更换第二组s//\2/之间匹配的部分... (
  6. )删除所有期间。
  7. s/[.]//g打印出
  8. p终止该块。

答案 3 :(得分:1)

这也是一项工作:

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:如果已经进行了成功的替换,则跳转到标签c(自上次使用后读入最后一行并自上次使用t起,T )。

答案 4 :(得分:1)

使用以下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

答案 5 :(得分:1)

awk -F'[]F]' '{gsub(/\./,"")gsub(/ /,"")gsub(/ec/,"e c");print $2}' file

capture
capture
capture::capture::capture
capture::me::capture capture capture
capture-me