C#根据输入字符串查找子字符串

时间:2014-09-12 21:59:00

标签: c# regex string

我是C#的新手,所以我的经验不多。

对于一个简单的体验项目,我需要从句子中找到类似于我得到的输入的关键词。

现在看来解决方案比我想象的要复杂得多,所以请原谅我缺乏经验或知识。

我从我的数据库中获取一个字符串,该字符串可以包含任意数量的字母,其余字符串都是数字,但字符串中的字符总数必须用于匹配。

string ThisIsTheTemplateToLookFor = "AB12345678"

我有一个带有一些文字的字符串:

string FromThisStringINeedToFind = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s and here comes the text to find AB54925871";

使用ThisIsTheTemplateToLookFor可能必须构建一个正则表达式命令来查找类似的文本。

所以需要找到:

AB12345678
AB87654321
AB67812345
...
etc
...

正则表达式必须从样本字符串中查找两个字母和8个数字。 或者在不同的情况下,ThisIsTheTemplateToLookFor字符串可以是A1234正则表达式应该找到A1234A4321A3910等。

或者Tim Schmelter建议使用Levenshtein距离算法

对不起语言,因为我不是母语为英语的人

我认为他的观点是,搜索字符串的细微方式与尚未列举的方式不同,应该是找到的字符串。在示例中,搜索字符串为AB12345678,但应该发现的字符串为AB54925871

我的猜测是,如果搜索字符串是AB12345678,则应找到包含任意顺序的10个字符的任何10个字符子字符串。 - 斧头

  • 在第一个例子中,AB和任何8个数字应该给出结果。
  • 在第二个例子A中,任何4个数字都应给出结果。

2 个答案:

答案 0 :(得分:0)

由于您现在已经在your first question中澄清了要求,但我无法发布答案,因为它仍然关闭,我会把我的两分钱放在这里。

根据需要,你不需要正则表达式。你的样本:

string sample = "AB12345678";
string subject = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s and here comes the text to find AB54925871";

现在,您希望在句子中找到具有相同Length的单词,该单词以相同的字母开头,以相同数量的(连续)数字结尾:

string letters = string.Join("", sample.TakeWhile(Char.IsLetter));
int countDigits = sample.SkipWhile(Char.IsLetter).TakeWhile(Char.IsDigit).Count();

您可以使用此LINQ查询:

var matchingWords = subject.Split()  // splits by spaces, tabs and new-lines
    .Where(word => sample.Length == word.Length
        && letters == string.Join("", word.TakeWhile(Char.IsLetter))
        && countDigits == word.SkipWhile(Char.IsLetter).TakeWhile(Char.IsDigit).Count());
string word = matchingWords.FirstOrDefault();  // AB54925871

如果找不到匹配的单词,则返回null

如果你想找到所有并用逗号分隔它们:

string allWords = string.Join(",", matchingWords);

答案 1 :(得分:0)

从您的问题陈述中,我们不是在这里谈论火箭科学:只需创建一个像您一样的工厂方法

static Regex CreateRegularExpressionFromTemplate( string template )
{
  StringBuilder sb = new StringBuilder() ;

  foreach( char c in template )
  {
    if      ( char.IsLetter(      c ) ) sb.Append( @"\p{L}" ) ;
    else if ( char.IsNumber(      c ) ) sb.Append( @"\d"    ) ;
    else if ( char.IsWhiteSpace(  c ) ) sb.Append( @"\s"    ) ;
    else if ( char.IsPunctuation( c ) ) sb.Append( @"\p{P}" ) ;
    else throw new ArgumentOutOfRangeException("template") ;
  }

  string pattern = sb.ToString() ;
  Regex rx = new Regex( pattern ) ;
  return rx ;
}

哪个会改变这个

@"AB12345678"

进入这个

@"\p{L}\p{L}\d\d\d\d\d\d\d\d"

然后你可以做像

这样的事情
Regex rx = CreateRegularExpressionFromTemplate( "AB12345678" ) ;
Match m  = rx.Match( "This is zX98320987 speaking." ) ;

if ( m.Success)
{
  Console.WriteLine( "We matched '{0}'" , m.Value ) ;
}
else
{
  Console.WriteLine( "no match found" ) ;
}

获得预期的

We matched 'zX98320987'

编辑注意:如果您需要匹配字边界,您只需添加适当的正面后视和正向前瞻断言:

static Regex CreateRegularExpressionFromTemplate( string template )
{
  StringBuilder sb = new StringBuilder() ;

  sb.Append( @"(?<=(^|\W))" ) ; // require the match to at the beginning of a word
  foreach( char c in template )
  {
    if      ( char.IsLetter(      c ) ) sb.Append( @"\p{L}" ) ;
    else if ( char.IsNumber(      c ) ) sb.Append( @"\d"    ) ;
    else if ( char.IsWhiteSpace(  c ) ) sb.Append( @"\s"    ) ;
    else if ( char.IsPunctuation( c ) ) sb.Append( @"\p{P}" ) ;
    else throw new ArgumentOutOfRangeException("template") ;
  }
  sb.Append( @"(?=($|\W))" ; // require the match to end at the end of a word

  string pattern = sb.ToString() ;
  Regex rx = new Regex( pattern ) ;
  return rx ;
}