【问题标题】:Regexp delimiter "::" Tcl正则表达式分隔符 "::" Tcl
【发布时间】:2018-10-10 20:34:48
【问题描述】:

我有一个 IPv6 地址

> puts $addr
3ffe:0:4:ff00::fc:5

我想把它分成两组

  • 3ffe:0:4:ff00
  • fc:5

我尝试了“拆分”命令,但它不起作用。正则表达式给出以下结果:

> regexp -all -- {(\S+)[set z](\S+)} $addr match g1 g2
1
> puts $g1
3ff
> puts $g2
:0:4:ff00::fc:5

对拆分它们的方法有什么建议吗?

【问题讨论】:

  • (.*)::(.*) 也许?
  • 那行不通。 IPv6 地址的问题在于它在字符串中也有一个“:”。并且正则表达式将匹配单个“:”并在继续之前拆分。
  • (.*)::(.*) 永远不会匹配单个“:”

标签: regex tcl


【解决方案1】:

使用textutil::split package from tcllib

$ tclsh
% package require textutil::split
0.8
% set parts [::textutil::split::splitx "3ffe:0:4:ff00::fc:5" "::"]
3ffe:0:4:ff00 fc:5

【讨论】:

  • 基于正则表达式的拆分是一个已解决的问题。卢克,使用图书馆。
【解决方案2】:

split 仅拆分单个字符。您可以做的是将:: 换成其他东西,然后再拆分其他东西。例如,假设字符串中不可能有字符@,那么您可以先替换它,然后在@ 上拆分:

% set sub [string map {"::" "@"} $addr]
3ffe:0:4:ff00@fc:5
% set groups [split $sub "@"]
3ffe:0:4:ff00 fc:5

否则如果你想使用正则表达式,你可以匹配:

% regexp {(.+)::(.+)} $addr - part1 part2
1
% puts $part1
3ffe:0:4:ff00
% puts $part2
fc:5

您使用的表达式 (\S+)[set z](\S+) 实际上尝试按此顺序匹配:

  1. 非空格字符
  2. set<space>z 中的任意一个字符
  3. 非空格字符

这样(\S+) 将匹配(3ff)[set z] 将匹配e(\S+) 将匹配字符串的其余部分。如果您想让z 包含变量,则需要使用更像这样的东西(大括号防止替换[set z]\,但引号不会,因此,您将不得不如果您允许替换,请转义反斜杠):

regexp "(\\S+)[set z](\\S+)" $addr match g1 g2

regexp "(\\S+)${z}(\\S+)" $addr match g1 g2

我删除了 -all 标志,因为只有一个匹配项,所以在这种情况下,没有必要,尽管您可以保留 --

【讨论】:

  • @PJProudhon 好吗?如果您指的是我的陈述,它是在问题标签的上下文中提出的
  • @PJProudhon 这不是关于正则表达式风格的声明。 split 是 Tcl 中的一个字符串函数(不需要正则表达式),OP 一开始提到尝试它,但发现它不起作用。听起来你确实是突然冒出来的,所以我有点吃惊,但如果你想保留你的评论也没关系。
  • 考虑到您的反馈,我觉得我的评论太混乱了。然后我将其删除。
  • regexp -all -- "(\\S+)[set z](\\S+)" $val match f1 f2 工作。谢谢:-)
  • 文本中有很多非常少见的字符,例如\uFFFC(unicode对象替换),对这类事情很有用。
【解决方案3】:

对拆分它们的方法有什么建议吗?

保持简单,使用string map:

% set addr 3ffe:0:4:ff00::fc:5
3ffe:0:4:ff00::fc:5
% lassign [string map {:: " "} $addr] pt1 pt2
% puts $pt1
3ffe:0:4:ff00
% puts $pt2
fc:5

【讨论】:

  • 我注意到我的回答只是对 Jerry 使用 string map/ subst 组合的简化。在我看来,这没有必要。
  • @Nasir:你应该首先接受一个最适合你的答案,或者为你提供最有价值的见解......
  • 感谢提醒。我更新了接受的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-29
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
相关资源
最近更新 更多