如何在字符串中搜索值并转换值

How to search a string for values and convert values

我有一个 API 接受在进入服务器之前需要正确格式化的字符串。

进入服务器的格式如下

"{Country ABR} {Day/Hour} {State ABR} {Title} {hrs.} ({Month Year}.)"

客户可能发送的几种可能性:

"US Construction 7/70 hrs."

"IA Private hrs US.

"OIL US 8/70 hrs (Dec 2014).

转换用户输入后的几个有效示例是:

"US 7/70 MI Construction hrs."

"US IA Private hrs."

"US OIL 8/70 hrs. (Dec 2014)" 

转换器将输入排列成正确的顺序。 hrs 总是以句号结尾,并在句子外重新排列 ({Month Year}),如图所示。

到目前为止我有

       [TestMethod]
    public void TestMethod1()
    {
        var toConvert = "USA Construction 70/700 (Dec 2014) hrs";
        var converted = ConvertHOSRules(toConvert);

        Assert.AreEqual(converted, "USA 70/700 Construction hrs.(Dec 2014)");
    }

    private string ConvertHOSRules(string input)
    {
        //todo refactor
        string output = "";

        string country = Regex.Match(input, @"\b(USA|CAN|MEX)\b").Value +" ";
        string dateHours =  Regex.Match(input,@"\d{1,2}\/\d{1,3}").Value + " ";
        string hrs = Regex.Match(input, @"\b(hrs)\b").Value ;
        var date = Regex.Match(input, @"\(([a-zA-Z]+\s{1}[0-9]{4})\)").Value + " ";
        string title = input.Replace(country, "").Replace(date, "").Replace(dateHours, "").Replace(hrs, "");
        output = $"{country} {dateHours} {title} {hrs}.{date}";
        return output;

    }

这已经过去了,我需要重构.. + " " 就像是懒惰的程序员的 null guard

这个问题很有趣,特别是如果我们想为它设计算法的话,因为我猜我们的正则表达式是不必要的。


如果我们希望用表达式来做到这一点,我将从一个简单的表达式开始,例如在两个捕获组中列出可能的国家和州:

(US|UK|FR)
(CA|WA|IA|MO|MI)

那么我们的时间是well-structured:

(\d+\/\d+)

月份 (.+?) 和年份 ([0-9]+) 也是如此:

\(((.+?)\s+([0-9]+))\)

这里是我们将面临其他关键字问题的地方,例如 ConstructionOIL,我们可以添加最少 3 个字符,以免与州和国家发生冲突:

([A-Z][a-z]{2,}|[A-Z]{3,})

最后我们会通过收集所有空格和其他剩余的字符来清理我们的字符串,例如 hrs. 这只是重复,我们可能不想匹配或捕获它。

(.*?)

最后,我们将使用交替组合:

(US|UK|FR)|(CA|NY|IA|TX|MI)|(\d+\/\d+)|\(((.+?)\s+([0-9]+))\)|([A-Z][a-z]{2,}|[A-Z]{3,})|(.*?)

DEMO

测试

using System;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        string pattern = @"(US|UK|FR)|(CA|NY|IA|TX|MI)|(\d+\/\d+)|\(((.+?)\s+([0-9]+))\)|([A-Z][a-z]{2,}|[A-Z]{3,})|(.*?)";
        string input = @"US 7/70 MI Construction hrs.
US IA Private hrs.
US OIL 8/70 hrs. (Dec 2014)
UK 7/70 MI Construction hrs.
UK IA Private hrs.
UK OIL 8/70 hrs. (Dec 2014)
FR 7/70 MI Construction hrs.
FR IA Private hrs.
FR OIL 8/70 hrs. (Dec 2014)";
        RegexOptions options = RegexOptions.Multiline;

        foreach (Match m in Regex.Matches(input, pattern, options))
        {
            Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
        }
    }
}

DEMO

正则表达式

如果不需要这个表达式,它可以是 modified/changed in regex101.com

正则表达式电路

jex.im 可视化正则表达式: