【问题标题】:Get Substring without Regular Expression获取没有正则表达式的子字符串
【发布时间】:2017-03-18 18:02:27
【问题描述】:

这将是一个很长的问题,所以请耐心等待我(也请帮助我,因为我已经无能为力了)但让我给你我的背景先做。

由于连接不同的东西(它最终成为一个长字符串),我有一种压力。一个例子是:

C1;371 (Huz-fer)/GT(BLEA)56Mar<sup>nq5(LAG-HQRZ3*,-tMoline)KTA</sup> (iBet-huz/W-HEAPP) [stock 12345] [pregnant]

让我分解一下字符串的结构。


正式名称

C1;371 (Huz-fer)/GT(BLEA)56Mar<sup>nq5(LAG-HQRZ3*,-tMoline)KTA</sup>

这将始终位于字符串的开头,并且可能是一个长名称,其中还可能包含包含在 () 中的字符串。


型号名称

(iBet-huz/W-HEAPP)

这是我需要获取和提取的内容 - 它总是紧跟在正式名称之后,并且总是包含在 () 中。 它还可能包含包含在另一组 () 中的子字符串 - 所以像 (iBet-huz/W-(vuts)HEAPP) 这样的东西是完全可能的


库存

[stock 12345]

这将始终包含在[] 中,并以单词stock 开头。


动物类型

[pregnant]

这将始终位于包含在[] 中的字符串的末尾。


在上面的示例中,我需要获取 型号名称 (iBet-huz/W-HEAPP) 或提到的其他情况 (iBet-huz/W-(vuts)HEAPP)。在 Oracle SQL 中,我可以很容易地做到这一点 使用正则表达式:

SELECT DISTINCT REGEXP_SUBSTR(ss.strain_value, '\(.*?\)', 1, REGEXP_COUNT(ss.strain_value, '\(.*?\)')) AS name
FROM species_strain ss
WHERE INSTR(ss.strain_value, '(', 1, 1) > 0
ORDER BY name ASC

但我现在的问题是我需要在第三方中做同样的事情 剥离了我可以使用的可用功能的软件 Oracle(REGEXP_SUBSTRREGEXP_COUNT)被删除 这意味着我在查询时不能做任何字符串操作 那个软件。幸运的是,他们提供了一些查询之外的工具 用于字符串操作(虽然没有那么广泛)。


可用的字符串操作函数

  • Ascii(String) - 返回字符表达式中最左边字符的 ASCII 码值。
  • Char(Number) - 将整数 ASCIICode 转换为字符。
  • CharIndex(String1, String2) - 返回 String1 在 String2 中的起始位置,从零字符位置开始到字符串的结尾。
  • CharIndex(String1, String2, StartLocation) - 返回 String1 在 String2 中的起始位置,从 StartLocation 字符位置开始到字符串的结尾。
  • Concat(String1, ... , StringN) - 返回一个字符串值,其中包含当前字符串与任何其他字符串的连接。
  • Contains(String, SubString) - 如果 SubString 出现在 String 中,则返回 True;否则,返回 False。
  • EndsWith(String, EndString) - 如果 String 的结尾匹配 EndString,则返回 True;否则,返回 False。
  • Insert(String1, StartPosition, String2) - 将 String2 插入到 String1 中由 StartPositon 指定的位置。
  • Len(Value) - 返回一个整数,其中包含字符串中的字符数或存储变量所需的标称字节数。
  • Lower(String) - 返回小写字符串。
  • PadLeft(String, Length) - 左对齐定义的字符串中的字符,用空格字符填充其左侧,直到指定的总长度。
  • PadLeft(String, Length, Char) - 将定义字符串中的字符左对齐,用指定的 Char 填充其左侧,直到达到指定的总长度。
  • PadRight(String, Length) - 将已定义字符串中的字符右对齐,用空格字符填充其左侧,直至达到指定的总长度。
  • PadRight(String, Length, Char) - 右对齐定义字符串中的字符,用指定的 Char 填充其左侧直到指定的总长度。
  • Remove(String, StartPosition, Length) - 从此实例中删除指定数量的字符,从指定位置开始。
  • Replace(String, SubString2, String3) - 返回 String1 的副本,其中 SubString2 已替换为 String3。
  • Reverse(String) - 反转字符串中元素的顺序。
  • StartsWith(String, StartString) - 如果 String 的开头匹配 StartString,则返回 True;否则,返回 False。
  • Substring(String, StartPosition, Length) - 从字符串中检索子字符串。子字符串从 StartPosition 开始并具有指定的长度。
  • Substring(String, StartPosition) - 从字符串中检索子字符串。子字符串从 StartPosition 开始。
  • ToStr(Value) - 返回对象的字符串表示形式。
  • Trim(String) - 从字符串中删除所有前导和尾随空格字符。
  • Upper(String) - 返回大写字符串。

通过上面的这些可用函数,我能够为模型名称为 (iBet-huz/W-HEAPP) 的第一种情况提出解决方案,但对于模型名称为 (iBet-huz/W-(vuts)HEAPP) 的下一种情况却没有。

MY CURRENT SOLUTION(没有解决第二种情况)

在我们使用的第三方软件中,您可以创建一个变量并使用上面列举的函数。

--------------------------------------------------------------------------
[reversed_strain]
--------------------------------------------------------------------------
Trim(Reverse([STRAIN_VALUE]))

--------------------------------------------------------------------------
[removed_animal_type]
--------------------------------------------------------------------------
Iif(
    StartsWith([reversed_strain], ']'),
    Trim(Remove([reversed_strain], 0, CharIndex('[', [reversed_strain]) + 2)),
    [reversed_strain]
)

--------------------------------------------------------------------------
[model_name]
--------------------------------------------------------------------------
Iif(
    StartsWith([removed_animal_type], ')'),
    Trim(Reverse(Substring([removed_animal_type], 1, CharIndex('(', [removed_animal_type]) - 1))),
    [STRAIN_VALUE]
)

我的方法背后的基本思想:

  1. 反转整个字符串,将动物类型、库存和型号名称放在字符串的开头。
  2. 删除动物类型 - 将股票放在字符串的开头。
  3. 删除库存 - 将型号名称放在字符串的开头。
  4. 获取从开头到第一个 ( 的字符串 - 我要查找左括号的原因是因为我颠倒了字符串。

您能否帮我修改我的解决方案,以便我还可以考虑第二种情况,我可以在模型名称中包含任意数量的 () p>

我知道这个问题已经很长了,但如果您需要更多信息,请告诉我。

附录

我的解决方案没有显示我删除字符串的 stock 部分,但这很好,我可以做与删除动物类型相同的事情,所以不用担心 - 想象一下 @987654373 @ 已被删除。

【问题讨论】:

  • 我是否正确地假设您使用 DevExpress 标记了它,因为您试图在 XtraReport 或 XtraGrid 控件中输出它并使用它们各自的内置函数?
  • @Brendon 是的,我们的第三方软件利用 DevExpress XtraReport 控件生成报告/发票/卡片/等。
  • 如果是这种情况,您不需要简单地使用内置的 CalculatedField 函数。您可以处理 CalculatedField.GetValue 事件并使用完整的 RegEx 和 .NET String 函数来解析您的字符串。
  • @Brendon 好的——我完全忘记了我能做到这一点。问题是我已经有将近十年没有使用 C#了,所以我认为我对这门语言的了解已经过时了。我会尝试下面的答案,希望我能正确地自定义它。

标签: string devexpress substring string-matching


【解决方案1】:

如果您的formal name 和您的model name 用空格分隔,那么您可以使用它来查找model name
示例如下:

--------------------------------------------------------------------------
[strain_removed]
--------------------------------------------------------------------------
Substring([strain_value], 0, CharIndex(') [', [strain_value]) + 1)

--------------------------------------------------------------------------
[model_name]
--------------------------------------------------------------------------
Substring([strain_removed], Len([strain_removed]) - CharIndex('( ', Reverse([strain_removed])) - 1)

你可以试试这个例子:

var table = new System.Data.DataTable();
table.Columns.Add("strain_value");

table.Rows.Add("C1;371 (Huz-fer)/GT(BLEA)56Mar<sup>nq5(LAG-HQRZ3*,-tMoline)KTA</sup> (iBet-huz/W-HEAPP) [stock 12345] [pregnant]");
table.Rows.Add("C1;371 (Huz-fer)/GT(BLEA)56Mar<sup>nq5(LAG-HQRZ3*,-tMoline)KTA</sup> (iBet-huz/W-(vuts)HEAPP) [stock 12345] [pregnant]");

var labelItem1 = new XRLabel();
labelItem1.DataBindings.Add("Text", null, "model_name");

var detail = new DetailBand();
detail.Controls.AddRange(new XRControl[] { labelItem1 });

var strain_removed = new CalculatedField();
strain_removed.Name = "strain_removed";
strain_removed.Expression = "Substring([strain_value], 0, CharIndex(') [', [strain_value]) + 1)";

var model_name = new CalculatedField();
model_name.Name = "model_name";
model_name.Expression = "Substring([strain_removed], Len([strain_removed]) - CharIndex('( ', Reverse([strain_removed])) - 1)";

var report = new XtraReport();
report.Bands.Add(detail);
report.DataSource = table;
report.CalculatedFields.AddRange(new[] { strain_removed, model_name });

report.ShowRibbonPreview();

但在XtraReport 中,您还可以使用脚本或事件以任何 .net 语言执行您想做的任何事情。例如,可以使用xrLabel控件的BeforePrint事件和GetCurrentColumnValue方法获取当前列值:

using System.Text.RegularExpressions;

private void label1_BeforePrint(object sender, PrintEventArgs System.Drawing.Printing.PrintEventArgs e)
{
    string strain_value = GetCurrentColumnValue("strain_value").ToString();

    string model_name = ... // <= Your regex computations.

    label1.Text = model_name;
}

【讨论】:

  • 抱歉,我似乎无法遵循您的解决方案。你能修改它,以便我可以看到每一步吗?我将您的第一个解决方案复制到我的计算字段的脚本中并预览了报告并打开了无数个窗口 - 我不得不关闭我的计算机。第二种解决方案根本不验证。我错过了什么吗?
  • 好的 - 我现在能够遵循第二个解决方案。我不得不将using System.Data;using System.Drawing.Printing; 放在脚本窗口的顶部。现在我该如何进行正则表达式计算?
  • @PatrickGregorio 我的第一个示例是粘贴运行类型。它不打算用作计算字段的脚本。您可以将此代码粘贴到一些点击事件中,例如PreviewClick。对于正则表达式计算,添加 using System.Text.RegularExpressions; 并按照 MSDN 主题获取 Regex Class
猜你喜欢
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
相关资源
最近更新 更多