【问题标题】:Best way to grab a specific position from a string从字符串中获取特定位置的最佳方法
【发布时间】:2016-11-11 10:55:36
【问题描述】:

我已经查看了很多关于这个问题的不同看法,答案会有所不同,具体取决于问题的措辞方式。看来您可以使用 split 或使用正则表达式来执行此操作。

我正在做的是使用 WMI 返回主板的 BIOSVersion。无论出于何种原因,制造商在其中投入的不仅仅是版本号。在整个字符串中,版本号位于句点分隔字符串的第三位。在第二个位置的值总是 86A。在这个例子中,版本实际上是0460.SIX7910J.86A.0460.2012.0327.1627

那么,就我正在做的事情而言,哪一个是“最佳实践”?查询表达式中的正则表达式,循环使用 split 或其他我还没有找到的结果?

作为参考,这是我正在使用的 C# WMI 代码。示例代码使用的是 Windows 窗体,因为那是 WMI 代码创建器输出的内容。我将在 WPF 项目中使用它,但我不知道这对问题的本质意味着太多。我想我可以计算出所需的代码,但我正在尝试了解哪种方式是最好的方式。

感谢您提供的任何帮助。如果代码没有全部显示在代码块中,我提前道歉。我以为我按照说明进行操作,但是在代码块的示例显示中,它在代码块中有一点代码,然后转到普通文本,然后返回到代码块。希望实际的渲染更清晰。

using System;
using System.Management;
using System.Windows.Forms;

namespace WMISample
{
    public class MyWMIQuery
    {
        public static void Main()
        {
            try
            {
                ManagementObjectSearcher searcher = 
                    new ManagementObjectSearcher("root\\CIMV2", 
                    "SELECT BIOSVersion FROM Win32_BIOS"); 

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    Console.WriteLine("-----------------------------------");
                    Console.WriteLine("Win32_BIOS instance");
                    Console.WriteLine("-----------------------------------");

                    if(queryObj["BIOSVersion"] == null)
                        Console.WriteLine("BIOSVersion: {0}", queryObj["BIOSVersion"]);
                    else
                    {
                        String[] arrBIOSVersion = (String[])(queryObj["BIOSVersion"]);
                        foreach (String arrValue in arrBIOSVersion)
                        {
                            Console.WriteLine("BIOSVersion: {0}", arrValue);
                        }
                    }
                }
            }
            catch (ManagementException e)
            {
                MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
            }
        }
    }
}

【问题讨论】:

  • 使用字符串方法 IndexOf() 查找“86A”。使用 Substring 获取字符串。在 Regex 之前始终使用简单的 String 方法。当字符串方法变得复杂时,使用正则表达式。如果有意义的话,将 String 方法和 Regex 结合使用没有错。
  • 与您的实际问题无关,但在测试 queryObj["BIOSVersion] 是否为空(或者我错过了什么?)之后,显示 queryObj["BIOSVersion] 的意义不大。
  • 这可能不言而喻,但实际的“BIOSVersion”取决于制造商。在我的机器上,它是一个连字符分隔的列表。
  • not 如某些答案中所建议的那样使用.Split('.') 的唯一原因是如果您需要一些异常高性能。我知道这些场景存在,但它们并不典型——它们很少见。即使那样,我也不会三思而后行,除非您加载测试并发现此操作会导致性能问题。因此,除非您需要在几分钟内处理完大陆上的每块主板,否则几乎没有任何影响。
  • 可能没有必要。这在 PowerShell 中适合您吗? (Get-WmiObject -Class win32_bios).SmBIOSBIOSVersion

标签: c# regex winforms wmi wmi-query


【解决方案1】:

如果版本总是从开始的第三个,这是最简单的方法。

string s = "SIX7910J.86A.0460.2012.0327.1627";

        string[] arr = s.Split('.');

        Console.WriteLine(arr[2]);

希望清楚。

【讨论】:

  • 感谢所有回复的人。几乎所有的回复都很棒!它帮助我澄清了很多事情。
【解决方案2】:

第一:使用@Saket的方法,清晰易读易懂。
为了完整起见,这里是一种正则表达式方法:

(?:[^.]+\.){2}\K # match anything not a dot, followed by a dot
                 # two times and throw it away afterwards
([^.]+)          # match anything not a dot

这会给你0460,见a demo on regex101.com

【讨论】:

  • 非常有用的正则表达式链接,立即加入书签。感谢分享。
【解决方案3】:

在我看来,当您有机会仅使用 String 方法来实现字符串操作时(并且实现并不复杂),那就去做吧,不要使用正则表达式。这是因为大多数方法使用低级 C++ 实现,而 Regex 会导致更多开销。您的整个代码大约需要 50 毫秒,所以我认为没有必要对其进行更多优化。只需将其添加到您的循环中:

foreach (String arrValue in arrBIOSVersion)
{
    string[] split = arrValue.Split('.');

    string version;
    if (split.Length > 3)
        version = split[2];
}

【讨论】:

    猜你喜欢
    • 2012-11-25
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    相关资源
    最近更新 更多