正则表达式匹配一个单词与数字

时间:2011-03-10 16:19:15

标签: regex perl

我正在使用Text::Ngrams来确定字符串中的单词组合。但是,我需要保留带有数字的单词。我已经确定$o->{tokenrex}是我需要修改的内容,但我无法确定它的正确正则表达式。

原作是qr/([a-zA-Z]+|(\d+(\.\d+)?|\d*\.\d+)([eE][-+]?\d+)?)/;,但我认为我还需要更多内容:

 qr/([a-zA-Z]+|(?<=\w)(\d+(\.\d+)?|\d*\.\d+)([eE][-+]?\d+)?(?=\w)|(\d+(\.\d+)?|\d*\.\d+)([eE][-+]?\d+)?)/;

如果我正在阅读正则表达式,那么应该匹配任意数量的字母字符,或者在它之前和之后具有单词字符的“数字”,或者“数字”。除了它将我的“单词”分成单独的标记。我正在使用的示例单词是“ A1X ”。

任何帮助都会很棒。

4 个答案:

答案 0 :(得分:4)

你们这些都太复杂了。原始正则表达式匹配仅由字母或数字组成的单词(整数,浮点数,包括指数表示法)。

如果您需要匹配由字母和数字组成的单词,那么正则表达式为[a-zA-Z\d]+。根据模块文档,您还需要指定要跳过的内容,并且匹配[^a-zA-Z\d]+

$self->{tokenrex} = qr/([a-z\d]+)/i;
$self->{skiprex}  = qr/([^a-z\d]+)/i;

如果您需要识别模块文档中显示的数字,请告诉我,我很乐意为您添加。根据您的描述,这听起来并不像您需要的那样。

答案 1 :(得分:0)

所以看起来你有几件事需要修复。如果我明白你的意思,那么将单词分成不同的标记就很容易了:只使用非捕获组。如果您不想围绕(?:foo)创建新的捕获组,请使用foo;如果你这样做,请使用(foo)

无论如何,你想要的模式对我来说是这样的:

p{L}*(?:\d*\.)?\d+(?:[eE][-+]?\d+)?(?:(?<=p{L}(?:\d*\.)?\d+(?:[eE][-+]?\d+)?)p{L}+)?

说明:

p{L}*                 #Zero or more letter characters (note that this is broader than [a-zA-Z], as it allows accent marks and so forth)
(?:\d*\.)?\d+         #Slightly simplified version of your number-matching pattern
(?:(?<=p{L}...)p{L}+)? #Optionally match trailing letters, but only if there are letters at the beginning

希望我明白你在寻找什么。一个问题是[eE];这将引入一些含糊之处。例如,如果你得到一个像 A3E4D 这样的字符串,那么E是一个字母还是一个指数?我对此有一些想法,但它会更长,更复杂。让我知道规则是什么,我会编辑,我只是​​不想让这更令人困惑,直到我确定你在寻找什么。

答案 2 :(得分:0)

(?<=...)(?=...)构造是后视和前瞻表达式,它们匹配的文本包含在与整个常规匹配的文本中表达。

作为一个更简单的例子,对于$_ = "A1X",正则表达式

qr/(?<=A)1(?=X)/

与字符串$_匹配,但与表达式匹配的文字(例如,在$&中)只是1,而不是A1X

您可以在原始表达式中添加另一个子句:

qr/([a-zA-Z]+|[a-zA-Z][a-zA-Z0-9]+[a-zA-Z]|(\d+(\.\d+)?|\d*\.\d+)([eE][-+]?\d+)?)/

(这将与A1B2C3D相匹配 - 目前尚不清楚你是否希望它这样做)

答案 3 :(得分:0)

试试这个:

qr/(\b[a-zA-Z]([a-zA-Z\d]+[a-zA-Z])?\b|(\d+(\.\d+)?|\d*\.\d+)([eE][-+]?\d+)?)/

但请注意,此正则表达式(和原始版本)将匹配单词“边缘”上的数字。