C#正则表达式 - 获取字符串中的第一个匹配项

6

我有一个输入字符串,格式如下:

level=<device[195].level>&name=<device[195].name>

我想创建一个正则表达式来解析每个<device>标签,例如,我期望从我的输入字符串中匹配到两个项目:<device[195].level><device[195].name>

到目前为止,我已经使用了这个模式和代码,但它总是将两个设备标签作为单个匹配项:

var pattern = "<device\\[[0-9]*\\]\\.\\S*>";
Regex rgx = new Regex(pattern);
var matches = rgx.Matches(httpData);

结果是 matches 将包含一个值为 <device[195].level>&name=<device[195].name> 的单个结果。
我猜应该有一种方法来“终止”这个模式,但我不确定是什么。

没时间回答所有问题,但关键在于非贪婪匹配。在 * 后面加上 ? 以使其匹配最小可能(非贪婪),而不是最大可能(贪婪)。 - Chris
5个回答

8

使用非贪婪量词

<device\[\d+\]\.\S+?>

此外,对于转义正则表达式,请使用原样字符串,这将使它们更易读:
var pattern = @"<device\[\d+\]\.\S+?>";

作为一个侧面的注意事项,我猜在你的情况下使用\w而不是\S可能更符合你的意图,但我保留了\S,因为我无法确定。

1
现在我想让那个踩我评论的人来证明我错了... http://regex101.com/r/kX3hK2/1 - Lucas Trzesniewski
@Lucas 在 \d* 后面加上 ? 是不必要的,因为 \d* 不会匹配 ]。此外,你的正则表达式将匹配 <device[].> 这样过于普遍的字符串。 - dognose
1
@dognose 你说的 ? 是对的,我想我太习惯默认使用非贪婪模式了。不过最终结果完全一样。我保留了 *,因为这是 OP 中的内容,而且我不知道提问者的用例。但是,这是否使它成为一个不好的答案呢? - Lucas Trzesniewski
1
@dognose:你是否了解用户输入字符串的内部信息?说“<device[].>”太常见了,这对我来说相当奇怪,因为我很少看到这样的字符串,而且OP也没有提到过这样的字符串。 - Chris

3
我想创建一个正则表达式,以解析每个<device>标签。
I'd expect two items to be matched from my input string: 
   1. <device[195].level>
   2. <device[195].name>

这应该可以工作。从索引1获取匹配的组。
(<device[^>]*>)

演示实况

程序中使用的字符串字面量:

@"(<device[^>]*>)"

1
请留下评论。 - Braj
@dognose 不要输入任何不被 OP 所允许的内容。 - Braj
你“完美的匹配,兄弟”示例是荒谬的,因为它与 OP 所说的字符串完全不同。 - Chris
如果是这种情况,那么我可以有成千上万种方法来使其无效。 - Braj
根据输入,它应该只是 [195],对吧? - Braj
显示剩余5条评论

3
取决于您需要匹配多少角块的结构,但您可以这样做。
"\\<device.+?\\>"

2

更改您的重复运算符,使用\w而不是\S

var pattern = @"<device\[[0-9]+\]\.\w+>";

String s = @"level=<device[195].level>&name=<device[195].name>";
foreach (Match m in Regex.Matches(s, @"<device\[[0-9]+\]\.\w+>"))
         Console.WriteLine(m.Value);

输出

<device[195].level>
<device[195].name>

1
使用命名匹配组并创建Linq实体投影。将有两个匹配项,因此可以分离单个项目:
string data = "level=<device[195].level>&name=<device[195].name>";

string pattern = @"
(?<variable>[^=]+)     # get the variable name
(?:=<device\[)         # static '=<device'
(?<index>[^\]]+)       # device number index
(?:]\.)                # static ].
(?<sub>[^>]+)          # Get the sub command
(?:>&?)                # Match but don't capture the > and possible &  
";

 // Ignore pattern whitespace is to document the pattern, does not affect processing.
var items = Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace)
                .OfType<Match>()
                .Select (mt => new
                  {
                     Variable = mt.Groups["variable"].Value,
                     Index    = mt.Groups["index"].Value,
                     Sub      = mt.Groups["sub"].Value
                  })
                 .ToList();

items.ForEach(itm => Console.WriteLine ("{0}:{1}:{2}", itm.Variable, itm.Index, itm.Sub));

/* Output
level:195:level
name:195:name
*/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接