3

我正在尝试通过以下方式将字符串拆分为标记(通过正则表达式):

示例 #1
输入字符串:'hello'
第一个标记:'
第二个标记:hello
第三个标记:'

Example #2
输入字符串:'hello world'
第一个标记:'
第二个标记:hello world
第三个标记:'

示例 #3
输入字符串:hello world
第一个标记:hello
第二个标记:world

即,仅当字符串不在单引号中时才拆分字符串,并且单引号应在其自己的标记中。

这是我到目前为止所拥有的:

string pattern = @"'|\s";
Regex RE = new Regex(pattern);
string[] tokens = RE.Split("'hello world'");

这将适用于示例 #1 和示例 #3,但不适用于示例 #2。我想知道理论上是否有一种方法可以用正则表达式实现我想要的

4

8 回答 8

5

您可以构建一个简单的词法分析器,这将涉及一个一个地使用每个标记。因此,您将拥有一个正则表达式列表,并尝试在每个点匹配其中一个。如果您的输入超出了非常简单的范围,这是最简单、最简洁的方法。

于 2010-02-09T21:55:30.317 回答
3

使用令牌解析器拆分成令牌。使用正则表达式查找字符串模式

于 2010-02-09T21:56:33.450 回答
2

'[^']+'将匹配单引号内的文本。如果你想把它分组,(')([^']+)('). 如果未找到匹配项,则只需使用常规字符串拆分。我认为尝试用一个正则表达式完成整个事情是没有意义的。

编辑:从您对问题的评论看来,您实际上希望将其应用于更大的文本块,而不仅仅是像您指出的那样简单输入。如果是这种情况,那么我认为正则表达式不是您的答案。

于 2010-02-09T21:53:15.870 回答
1

您可以先拆分带引号的字符串,然后再进行标记化。

foreach (String s in Regex.Split(input, @"('[^']+')")) {
    // Check first if s is a quote.
    // If so, split out the quotes.
    // If not, do what you intend to do.
}

(注意:您需要模式中的括号以确保 Regex.Split 也返回这些括号)

于 2010-02-09T22:01:10.893 回答
1

不完全是您正在尝试做的事情,但是当您寻找解决方案时,正则表达式条件可能会有所帮助:

(?<quot>')?(?<words>(?(quot)[^']|\w)+)(?(quot)')

如果找到引用,则匹配,直到找到非引用。否则查看单词字符。您的结果位于名为“quot”和“words”的组中。

于 2010-02-09T22:04:36.910 回答
1

虽然可以'单独匹配和里面的文本,也可以单独匹配文本,但 RegExp 不允许无限数量的匹配。或者更好地说,您只能匹配您在表达式中明确声明的那些对象。所以((\w+)+\b)理论上可以一一匹配所有单词。外部组将正确匹配整个文本,内部组也将正确匹配单独的单词,但您只能引用最后一个匹配项。

没有办法匹配一组匹配的匹配项(奇怪的句子)。唯一可能的方法是匹配字符串,然后将其拆分为单独的单词。

于 2010-02-09T22:05:44.833 回答
1

您将很难Split在这里使用,但您可以使用 aMatchCollection来查找字符串中的所有匹配项:

string str = "hello world, 'HELLO WORLD': we'll be fine.";
MatchCollection matches = Regex.Matches(str, @"(')([^']+)(')|(\w+)");

正则表达式在单引号之间搜索字符串。如果它找不到一个,它只需要一个单词。
现在它变得有点棘手 - .net 返回一个Matchs 的集合。每个 Match 有几个Groups - 第一个 Group 有整个字符串 ( 'hello world'),但其余的有子匹配 ( ', hello world, ')。此外,您会得到许多空的不成功组。
您仍然可以轻松迭代并获得匹配项。下面是一个使用 LINQ 的示例:

var tokens = from match in matches.Cast<Match>()
             from g in match.Groups.Cast<Group>().Skip(1)
             where g.Success
             select g.Value;

tokens is now a collection of strings:
hello, world, ', HELLO WORLD, ', we, ll, be, fine

于 2010-02-10T06:10:24.630 回答
0

试试这个正则表达式:

([']*)([a-z]+)([']*)

这会在字符串的开头和结尾找到 1 个或多个单引号。然后它会在 az 集中找到 1 个或多个字符(如果您不将其设置为不区分大小写,它只会找到小写字符)。它将这些分组,以便第 1 组具有 ',第 2 组(或更多)具有被任何非字符 a - z 分割的单词,最后一组具有单引号(如果存在)。

于 2010-02-09T22:02:24.323 回答