我尝试使用以下regex
表达式从文件中读取一行:
^([A-z.]+?\\s?[A-z]+)\\s([A-z]+)\\s(\\d{7})\\s(\\d?\\d.\\d)$
在线上:
斯内德0000574 10.0
(To明确:目的是使任何带有字符[a-z]、[A-Z]或点的单词与[A-z.]+部分匹配。)
然而,正则表达式不能识别W.W.中的第二个点,这让我觉得很奇怪。方括号和+组合在一起不就意味着它们内部的任何字符都可以接受,直到(这里)遇到空格吗?我发现了一个正则表达式,它确实可以工作,但不那么优雅:
^([A-z.]+[.\\s?[A-z]+)\\s([A-z]+)\\s(\\d{7})\\s(\\d?\\d.\\d)$
我希望他们能找到一个优雅的解决方案。能听听你的意见就好了。
像RegEx - Not parsing dot(.) at the end of a sentence这样的链接似乎没有回答我的问题。
2条答案
按热度按时间vuktfyat1#
空格分隔的数据只是常见CSV (Comma Separated Values)的一个不同变体。有许多方法可以用任意分隔符分隔字符串,但在C++中使用空格实际上非常容易:
[See示例here ]
一旦将值分隔为字符串向量,就可以将数值转换为它们的实际类型(例如使用
std::stod
)并存储到合适的对象中。当然,这并不能很好地处理名称中包含空格的情况,但可以在更高的层次上处理(通过检查结果向量的大小,并知道最后两个元素应该始终是特殊数字,其余的是名称)。
另一方面,问题中的正则表达式根本不处理它。:)
rggaifut2#
在你的正则表达式中,整个
W.W. Sneijder
被捕获在第一组中。看看你的正则表达式,我怀疑你是故意这样做的。我想你要的正则表达式是
^([A-z.]+?\s?[A-z]+)\s(\d{7})\s(\d?\d.\d)$
。或者,如果您希望
Sneijder
出现在第二个捕获中:^([A-z.]+?)\s([A-z]+)\s(\d{7})\s(\d?\d.\d)$
....或者您可能需要
^([A-z.]+?\s?[A-z]*)\s([A-z]+)\s(\d{7})\s(\d?\d.\d)$
(在第一个捕获组中使用*
而不是+
)。或
^([A-z.]+?(?:\s[A-z]+)?)\s([A-z]+)\s(\d{7})\s(\d?\d.\d)$
(可选空格+文本,同样在第一捕获组中)。所有4个表达式都应该与您的测试字符串匹配,但在其他测试字符串上的行为不同。
正则表达式当然也有改进,比如确保字符串不以
.
开头。只要您触及每个捕获组的内部,而不是跨捕获组的逻辑,就可以让正则表达式管理您想要的任何级别的控制,这不会影响文本解析之后的代码。
它总是有4个捕获组,除了我上面发布的第一个正则表达式只有3个捕获组,如果你需要将它转换为另一种类型,对文本有一些保证。