从设备名称中提取模型

4

Mozilla/2.0 (Linux; Android 2.0; KK; SAMSUNG SM-G900H Build/LRX21T) AppleWebKit

需要提取出 SAMSUNG SM-G900H Build/LRX21T

Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-G900H Build/LRX21T) AppleWebKit

需要提取出 SAMSUNG SM-G900H Build/LRX21T

Mozilla/5.0 (Linux; Android 5.1; XT1032 Build/LPBS23.13-56-2; wv) AppleWebKit

需要提取出 XT1032 Build/LPBS23.13-56-2

逻辑如下:

1. Take first [(.....)]
2. Take text after last semicolon [;]
3. Or take text after last semicolon [;] and before [; wv]

我现在有的是:

.*?\(.*;(?<model>.*?)(; wv)?\)

但是它只适用于前两个例子,对于第三个例子它会返回wv


你想仅使用正则表达式吗?或者其他逻辑也可以使用吗? - Gaurang Dave
我有一种感觉,如果模型名称中包含“()”,那么不使用正则表达式可能更容易完成。 - Evk
@Evk,不幸的是确实如此。Mozilla/5.0(Linux;Android 5.0.2;MotoE2(4G-LTE)Build/LXI22.50-53.8;wv)AppleWebKit/537.36(KHTML,like Gecko)Version/4.0 Chrome/45.0.2454.95 Mobile Safari/537.36 - Giorgi Nakeuri
你可能可以使用.NET正则表达式中的平衡组特性来完成这个任务,但我不认为有必要。 - Evk
3个回答

2
^(.*)\(.*;(?<model>(?!( wv))[^;()]*(\(.??\))?[^;)]*)+?(;.*)?\).*$

匹配

  • Mozilla/5.0 (Linux; Android 5.1; XT1032 Build/LPBS23.13-56-2; wv) AppleWebKit
  • Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-G900H Build/LRX21T) AppleWebKit
  • Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-G900H Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36
  • Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4) Build/MPJ24.139-23.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36

负向先行断言 ((?! wv)) 对我有帮助。

我猜你仍然可以使表达式更简洁,但是这个应该可以首先匹配(与/gi标志[全局,不区分大小写]一起使用)。

使其工作的重要条件:

  • 负向先行断言(?!...)
  • 惰性量词 ?? (第二个 '?' 使其成为惰性的,而不是贪婪的)

编辑:添加了匹配组中不能包含 ')' 的条件。 编辑2:修改表达式,使其适合更多的字符串。


你能检查一下为什么它对于这个Mozilla/5.0 (Linux; Android 5.0; SAMSUNG SM-G900H Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36无法工作吗? - Giorgi Nakeuri
@GiorgiNakeuri 我已经修改了它,使其与您的较长版本匹配。但是,如果设备名称包含“)”(如果存在),则不再与其匹配。 - Chrᴉz remembers Monica
现在好了!谢谢。我还注意到可能会有像这样的子字符串:Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4) Build/MPJ24.139-23.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36。它提取了 Moto G (4)。我猜那很难考虑? - Giorgi Nakeuri
如果您也想要这个功能,恐怕您需要使用递归正则表达式。您可以在此处查看相关问题(https://www.regular-expressions.info/recurse.html),但我现在无法使用此功能编辑我的答案,我需要在晚上回家后进行操作(我现在正在工作)。您需要允许“(”和“)”,只要它们的数量相等即可。 - Chrᴉz remembers Monica
好的,我明白了。谢谢! - Giorgi Nakeuri
@GiorgiNakeuri 我进行了修改,现在它可以捕获您所有的示例,甚至不需要递归正则表达式。但是请注意,它只匹配一对大括号。 - Chrᴉz remembers Monica

1
这个怎么样?
;\s*(?<model>([^;)])*)

我刚尝试了一下,第二个匹配项将会在命名组中返回所需的字符串。这将不匹配。
Mozilla/5.0 (Linux

这部分内容似乎与编程无关,您似乎不需要这部分。


工作正常,但问题是如何确定我需要哪个匹配项,因为它返回多个匹配项。不过还是谢谢! - Giorgi Nakeuri
难道不应该总是匹配相同的内容吗?因为唯一变化的只有wv。 :) - Matthias Grün
不幸的是,这只是一个例子,还有许多其他格式。例如 Opera/9.80 (Android; Opera Mini/16.0.2168/88.150; U; es) Presto/2.12.423 Version/12.16。问题在于,这种匹配是在 SQL Server 的 CLR 函数 [dbo].[DeviceExtractor] (@input NVARCHAR(MAX), @pattern NVARCHAR(MAX)) 中完成的,我需要它对所有类型的模式都是相同的。不想硬编码匹配的索引,因为对于不同的模式,它们将是不同的。 - Giorgi Nakeuri
如果您不知道括号内列表中的哪个项是设备名称,那么您就有问题了。因为这需要您能够检测设备名称(我认为这就是您要寻找的):( - Matthias Grün

0

只需要在分号上拆分成数组:

string[] parts = myUserAgent.Split(";");

现在您可以通过以下方式获取“三星...”:

string temp = parts[3];

最后使用“replace”函数删除无意字符。

谢谢,但我知道如何分隔字符串。问题是关于正则表达式解决方案的。 - Giorgi Nakeuri

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