我无法理解如何在 c# 中使用正则表达式或如何解决我的问题

Posted

技术标签:

【中文标题】我无法理解如何在 c# 中使用正则表达式或如何解决我的问题【英文标题】:I cannot wrap my head around on how to use regex in c# or how to solve my problem otherwise 【发布时间】:2020-10-27 20:36:24 【问题描述】:

我有以下问题:我无法分别从 Winforms 中的另一个文本框中提取特定字符串 C#:

在 TextboxA 中显示以下字符串(它是多行的。每个“”都是一行):

" OUT01: Valid      __GO__  103,2"
" OUT02: Valid      __GO__  -0,54"
" OUT03: Valid      __GO__  0,25"
" OUT04: Valid      ____LO  46,41"

在 Textbox1 中只需要显示“103,2”。在 Textbox2 中“-0,54”,在 Textbox3 中“0,25”和在 Textbox4 中分别为“46,41”。 我的 C# 项目的命名空间不允许浮点或双精度值。因此,在文本框 1-4 中必须有字符串值。因此 float.Parse(stringTextboxA);方法不起作用。用正则表达式怎么解决?

我已经试过了:

const string MeasurementValue1 = "  OUT01: Valid        __GO__  ";
var match = Regex.Match(MeasurementValue1, "  OUT01: Valid      __GO__  (*)");
txb_Textbox1.Text = match;

但这不起作用。一些更有经验的 C# 程序员和“正则表达式”专家可以告诉我一些问题吗?提前致谢!

最好的问候

【问题讨论】:

var match = Regex.Match(MeasurementValue1, @"OUT01:\s+Valid\s+__GO__\s+(\d+)")?.Groups[1].Value;? 我不会为此使用正则表达式。我只是将文本拆分为换行符,然后在每一行中搜索第一个空格,从右侧开始并在左侧工作。然后根据该字符位置拉出子字符串。 或匹配所有十进制值OUT\d+: Valid (?:__GO__|____LO) (-?\d+(?:,\d+)?)regex101.com/r/ehqu1V/1 在你已经尝试过的代码中,你试图匹配一个没有任何实际数字的字符串,所以无论你得到什么匹配都是空的。你也不能只匹配* - 你的意思是.* 匹配任何字符。 如果您的字段与示例中显示的一样恒定,那么从位置 27 开始的简单子字符串可能会做吗?否则我喜欢@BradleyUffner 的解决方案。 【参考方案1】:

* 本身就是一个量词。如果你在https://regex101.com/r/IYOlyB/1 上检查这个,你可以看到使用(*),红色星号表示前面的标记是不可量化的。

您可以将其设为(.*),但点匹配任何字符并且是十进制值的广泛匹配。


获取值的一个选项可能是使用例如量词\s2, 来确定空格数。

要匹配 GOLO 变体中的任何一个,您可以使用替换 | 来匹配其中任何一个。

十进制值可以在组1中捕获。

^\s+OUT\d+: Valid\s2,(?:__GO__|____LO)\s2,(-?\d+(?:,\d+)?)$

说明

^ 字符串开始 \s+OUT\d+: Valid匹配字符串的开头,使用\d+匹配1+位数 \s2, 匹配 2 个或更多空白字符 (?: 交替的非捕获组| __GO__ 字面匹配 |或者 ____LO 字面也匹配 )关闭非捕获组 \s2, 匹配 2 个或更多空白字符 (-?\d+(?:,\d+)?) 捕获组 1,匹配可选的 -,1+ 位和可选的小数部分 $字符串结束

.NET regex demo

【讨论】:

根据正则表达式演示,这似乎效果最好。不幸的是,我不能使用索引运算符,因为我的项目是用 C# 7.3 版编写的,而索引运算符至少需要 C# 8.0 版。我无法更改构建的 C# 版本,因为语言版本基于我的项目的框架版本......啊,当然:你是对的! * 本身只是一个量词。我忘记了“。”在“(.*)”中。 @s950mpc2000 如果您只想要匹配项,您可以使用积极的后向观察(?<=^\s+OUT\d+: Valid\s2,(?:__GO__|____LO)\s2,)-?\d+(?:,\d+)?$ 见demo 我用你的正则表达式写了以下代码string pattern = @"(?<=^\s+OUT\d+: Valid\s2,(?:__GO__|____LO)\s2,)-?\d+(?:,\d+)?\r?$"; string input = strLog; RegexOptions options = RegexOptions.Multiline; foreach (Match m in Regex.Matches(input, pattern, options)) Console.WriteLine("'0' found at index 1.", m.Value, m.Index); 。有用。它使用适当的索引在控制台中显示 4 个浮点值。如何在 4 个不同的文本框中插入这些值?所以第一个值 textbox1,第二个 textbox2 等等.. @s950mpc2000 如果这是设置值txb_Textbox1.Text = 并且值在m.Value 中的方法,则一种选择是通过索引从MatchCollection 获取值并分配m.Value.Text 属性。或者您可以使用索引循环集合,如果文本框是树结构中的子级,则获取父级的第 n 个子级。 我做了一个工作,因此找到了我的问题的解决方案。例如对于第二个值,它出现在 OUT02 之后我首先使用了以下正则表达式 @"^\s+(?:OUT02): Valid\s2,(?:__GO__|____LO)\s2,(-?\d+(?:,\d+)?)$";,然后我删除了我不需要的字符串 string.Remove(0, 23); 非常感谢您的所有输入和回答! :)【参考方案2】:

尝试以下:

        public Form1()
        
            InitializeComponent();
            textBox5.Multiline = true;
            textBox5.Text =
                " OUT01: Valid      __GO__  103,2\r\n" +
                " OUT02: Valid      __GO__  -0,54\r\n" +
                " OUT03: Valid      __GO__  0,25\r\n" +
                " OUT04: Valid      ____LO  46,41\r\n";

            List<TextBox> boxes = new List<TextBox>()  textBox1, textBox2, textBox3, textBox4 ;

            string pattern = @"[\d,\-\+]+\r\n";

            MatchCollection matches = Regex.Matches(textBox5.Text, pattern);

            string[] values = matches.Cast<Match>().Select(x => x.Value.Trim()).ToArray();

            for (int i = 0; i < values.Length; i++ )
            
                boxes[i].Text = values[i];
            

        

【讨论】:

【参考方案3】:

可以在这里扩展我的评论是您的数据在解析时的样子:

string myText = @""" OUT01: Valid      __GO__  103,2""
"" OUT02: Valid      __GO__  -0,54""
"" OUT03: Valid      __GO__  0,25""
"" OUT04: Valid      ____LO  46,41""";
int[] colsizes = @""" OUT01: Valid      ".Length, "__GO__  ".Length, 20; 
var myData = myText.Split('\n').Select(x => new 
    column1 = x.Substring(0, colsizes[0]).Trim(' ', '"'),
    column2 = x.Substring(colsizes[0], colsizes[1]).Trim(),
    column3 = decimal.TryParse(
        x.Substring(colsizes[0]+colsizes[1]).Trim().Replace("\"",""),
        NumberStyles.Any, new CultureInfo("tr-TR"), out decimal result)
        ? result : 0M
        
);

foreach (var d in myData)

        Console.WriteLine($"Column1: [d.column1], Column2: [d.column2], Column3: [d.column3]");


Form f = new Form();
DataGridView dgv = new DataGridView Dock=DockStyle.Fill, DataSource=myData.ToList();
f.Controls.Add(dgv);
f.Show();

PS:要显示数据,请尝试使用 DataGridView 代替文本框。你有数据行。 已编辑以显示在 DataGridView 中。

【讨论】:

【参考方案4】:

在您提供的 4 个字符串示例中,此正则表达式将仅匹配您指出需要包含的数字:

"\s[-0-9]1,,[0-9]1,2"

它查找空格“\s”,然后是 1 个或多个“1,”字符等于“-”或“0-9”,然后它必须找到一个逗号,然后正好是 1 个或 2 个“ 1,2" 数字 "0-9"。

你会像这样使用它:

var match = Regex.Match(" OUT04: Valid      ____LO  46,41", "\s[-0-9]1,,[0-9]1,2");

在这种情况下,匹配应该等于“46,41”。

试一试。你可以像我在这里一样测试你的正则表达式:https://www.regexpal.com/

【讨论】:

【参考方案5】:

您可以在没有正则表达式的情况下执行此操作,以满足您的要求,将文本按新行拆分,然后将行的最后一个值用空格拆分。我希望您的 c# 项目的命名空间不会强迫您使用正则表达式。 ;)

textboxA.Text = @"
 OUT01: Valid      __GO__  103,2
 OUT02: Valid      __GO__  -0,54
 OUT03: Valid      __GO__  0,25
 OUT04: Valid      ____LO  46,41
";

var withoutEmptyValues = StringSplitOptions.RemoveEmptyEntries;
var values = textboxA.Text
  .Split(new[]  Environment.NewLine , withoutEmptyValues)
  .Select(line => line.Split(new[]  " " , withoutEmptyValues).Last())
  .ToArray();

textBox1.Text = values[0];
textBox2.Text = values[1];
textBox3.Text = values[2];
textBox4.Text = values[3];

我建议使用更合适的控件来显示集合,例如列表框或数据网格视图或多行文本框。

【讨论】:

以上是关于我无法理解如何在 c# 中使用正则表达式或如何解决我的问题的主要内容,如果未能解决你的问题,请参考以下文章

何时不在 C#(或 Java、C++ 等)中使用 Regex

如何在 C# 2.0 中使用正则表达式处理 < 或 > 类型的字符串的编码

如何使用正则表达式(或 C# 函数)在一个变量中剪切 TEXT MESSAGE 并从此文本中剪切第二个变量 USERNAME?

如何使用 C# 在 Visual Studio 2010 中使用正则表达式或 HTMLAgilityPack 抓取 HTML 页面的特定部分?

如何在 C# 中读取正则表达式捕获

使用 C# 正则表达式。问题是如何使用“=”