2

我尝试了一些 sed 与 s/regex/../ 的组合,但没有成功。所以这是我的问题:我有一个看起来像这样的文本文件(PCLint 输出)

--- Module A
    Info: indented message 1
    Note: indented message 2
    Warning: indented message 3
--- Module B
--- Module C
    Info: indented message 1
--- Module D

我想将结果更改为以下内容(teamcity 服务消息):

[Start Module="Module A"]
    [Message Content="Info: indented message 1"]
    [Message Content="Note: indented message 2"]
    [Message Content="Warning: indented message 3"]
[End Module="Module A"]
[Start Module="Module B"]
[End Module="Module B"]
[Start Module="Module C"]
    [Message Content="Info: indented message 1"]
[End Module="Module C"]
[Start Module="Module D"]
[End Module="Module D"]

所以我知道文本将在每个“---”之间以某种方式分成块。然后我应该用正则表达式功能包装/替换文本块。但我不知道如何有效地做到这一点。理想情况下,我喜欢使用busybox 中可用的工具,例如sed、awk 等,以保持工具“简单”(需要在Win64 上工作)。

正则表达式我可以很好地工作,但我无法确定这个范围。对我有什么提示吗?

4

3 回答 3

4

awk 可以做到这一点。您将需要一个匹配的子句,/^---/该子句设置一个变量来记录您所在的模块,并且还输出前一个模块(如果有)的 End 行和下一个模块的 Start 行。然后是输出消息行的第二个子句。

$ cat input | awk '/^---/ { IFS=" "; oldM=M; M=$3; if (oldM) { print "[End Module=\"Module " oldM "\"]"; }; print "[Begin Module=\"Module " M "\"]"; } /^    (.*)$/ { gsub(/^ +/, "", $0); print "    [Message Content=\"" $0 "\"]"; } END { print "[End Module=\"Module " M "\"]"; }'
[Begin Module="Module A"]
    [Message Content="Info: indented message 1"]
    [Message Content="Note: indented message 2"]
    [Message Content="Warning: indented message 3"]
[End Module="Module A"]
[Begin Module="Module B"]
[End Module="Module B"]
[Begin Module="Module C"]
    [Message Content="Info: indented message 1"]
[End Module="Module C"]
[Begin Module="Module D"]
[End Module="Module D"]
于 2015-05-20T19:48:41.743 回答
1

sed为此目的提供了一个脚本:

翻译.sed:

:a
/Module/ {
    x
    s/.*Module (.*)/[End Module="\1"]/p
    x
    h
    s/(--- )(.*)/[Start Module="\2"]/p
    :b
    n
    /Module/! {
        s/(\s*)(.*)/\1[Message Content="\2"]/p
        bb
    }
    /Module/ {
        $!ba
        h
        s/(--- )(.*)/[Start Module="\2"]/p
        x
        s/.*Module (.*)/[End Module="\1"]/p
    }
}

像这样执行它:

sed -nrf translate.sed file.txt

输出:

[Start Module="Module A"]
    [Message Content="Info: indented message 1"]
    [Message Content="Note: indented message 2"]
    [Message Content="Warning: indented message 3"]
[End Module="A"]
[Start Module="Module B"]
[End Module="B"]
[Start Module="Module C"]
    [Message Content="Info: indented message 1"]
[End Module="C"]
[Start Module="Module D"]

这是相同版本的脚本,并添加了解释:

翻译.sed

# Define lable 'a' to iterate over modules
:a

# If the line module is matched ...
/Module/ {
    # Swap contents of hold and pattern buffer (current line)
    x

    # If the pattern buffer (former hold buffer)
    # contains something it is a module starting line.
    # Create and end tag out of it.
    s/.*Module (.*)/[End Module="\1"]/p

    # Get the current line back from hold buffer
    x

    h

    # Create a start module tag
    s/(--- )(.*)/[Start Module="\2"]/p

    # Create a label to iterate over messages
    :b

    # Get next line from input into pattern buffer
    # (Overwrite the pattern buffer)
    n

    # If it is not a module starting line ...
    /Module/! {

        # ... wrap it into the Message Content tag
        s/(\s*)(.*)/\1[Message Content="\2"]/p

        # and go on with the next line (step back to b)     
        bb
    }

    /Module/ {
        # if it is not the last line 
        # go on with the next module (step back to a)
        $!ba

        # on the last line ...

        # backup the current line in the hold buffer
        h

        # create start tag
        s/(--- )(.*)/[Start Module="\2"]/p

        # swap hold and pattern buffer
        x

        # create the end tag
        s/.*Module (.*)/[End Module="\1"]/p
    }
}

顺便说一句,它当然也可以是单线:D

sed -rn ':a;/Module/{;x;s/.*Module(.*)/[EndModule="\1"]/p;x;h;s/(---)(.*)/[StartModule="\2"]/p;:b;n;/Module/!{;s/(\s*)(.*)/\1[MessageContent="\2"]/p;;bb;};/Module/{;$!ba;h;s/(---)(.*)/[StartModule="\2"]/p;x;s/.*Module(.*)/[EndModule="\1"]/p;};};' file.txt
于 2015-05-20T20:15:19.083 回答
0
sed '# prepare loading
   s/^--- Module \(.*\)/[Start Module="\1"]\
[End Module="\1"]/
   s/^\([[:space:]]\{4\}\)\(.*\)/\1[Message Content="\2"]/
   H;$!d

# permutation
   x;s/\n/²/g;s/$/²/
:cycle
   s/²\(\[End[^²]*\)²\([[:space:]][^²]*\)²/²\2²\1/g
   t cycle
   s/.//;s/.$//;s/²/\
/g
' YourFile

使用递归修改

  • 更改消息行
  • 内存中的负载线和循环读数(没有输出d
  • 最后,加载内存内容
  • 用其他字符替换新行([^\n]在 posix 版本上不允许
  • 如有必要,使用消息内容置换模块的结尾
  • 重新添加新行(并删除额外的行)
  • 输出结果

通常,在 GNU sed 上不需要替换新行,因此直接在代码中进行更改²\n删除替换部分

于 2015-05-21T09:07:45.713 回答