在Tcl中需要正则表达式

时间:2017-09-29 17:56:18

标签: regex tcl

我想提取

来自下面提到的字符串的

"Memory: (71%)"。这(71%)每次都会改变。

字符串:"Memory: 327127123k. total, 2334437k used (71%), 9345624 k free (29%), 1123k buffers"

到目前为止,我已经制作了这个正则表达式,但它正在选择整行。

{[ regexp { Memory: (.*%)}

3 个答案:

答案 0 :(得分:1)

首先,您必须在正则表达式中转义(以使其与该字符匹配,因此:

{[ regexp { Memory: \(.*%\)}

这将匹配类似于

的字符串
"Memory: (71%)"

然后,您需要考虑要捕获的百分比之前和之后的字符。有几种方法可以做到这一点,包括:

  1. 您可以使用组来捕获您感兴趣的子表达式,并允许Memory和您的百分比之间的额外字符,所以:

    {[ regexp { Memory:.*(\(.*%\))}

  2. 将找到一个包含Memory:的字符串,后跟任意数量的以(XXXX5)结尾的字符,其中X是未确定的字符数,因此匹配{{1}之类的字符}但也可能是(71%)

    1. 您可以编码到您知道的更具体的上下文。当您知道要查找数字时,请不要使用通配符,所以也许

      (ABC%)

    2. 在匹配组中只会找到一个或多个数字,后跟{[ regexp { Memory:.*\(\d+%\)}。如果你知道你将有两个数字,请指定并获得更好的匹配:

      %

      `{[ regexp { Memory:.*\(\d\d%\)}`
      

      两者都在寻找两位数。

      最后,问一下为什么需要从字符串中提取`{[ regexp { Memory:.*\(\d{2}%\)}` 。您是否需要确保匹配的百分比仅来自这些行,表明文本中的其他行也有百分比?好的,您需要与Memory匹配。但是,如果这些百分比仅在Memory行中,则放弃该要求并使用简单的

      Memory

      将匹配任何包含两位数的括号,紧接着是`{[ regexp { \(\d{2}%\) }`

答案 1 :(得分:1)

正则表达式的关键是“我怎样才能使这个匹配只是我想要的部分?”并编写RE来处理这种情况。在这里,您要选择第一个单词,包括第一个冒号,跳过所有内容,直到之后的第一个括号,然后匹配并包括下一个括号。要记住的主要技巧是括号在用作文字时需要反斜杠,否则它们是RE元字符。

set str "Memory: 327127123k. total, 2334437k used (71%), 9345624 k free (29%), 1123k buffers"

if {[regexp {^([^:]*:)[^()]*(\([^()]*\))} $str -> a b]} {
    puts "$a $b"
} else {
    error "didn't match at all"
}

分解RE,有以下几个部分:

  • ^ - 字符串锚的开始。因为这是一个好主意。
  • ( [^:] * : ) - 捕获第一个冒号的所有内容,即所有不是冒号然后冒号的内容
  • [^()] * - 任意数量的非括号。
  • ( \( [^()] * \) ) - 围绕任何非括号序列捕获括号。

答案 2 :(得分:0)

set s "Memory: 327127123k. total, 2334437k used (71%), 9345624 k free (29%), 1123k buffers"

获取Memory: (71%)

format {Memory: (%s)} [regexp -inline {\d\d%} $s]

除非该行中的第一个单词发生更改,否则此(\d\d%)就是您需要匹配和提取的全部内容。

如果非空格字符组的数量不变,您实际上甚至不需要正则表达式:

format {Memory: %s} [string trim [lindex $s 5] ,]

两种变体都给出了

Memory: (71%)

如果可能,请始终避免使用正则表达式匹配。

文档: formatlindexregexpstringSyntax of Tcl regular expressions