【问题标题】:C# Parsing Text Within QuotesC# 解析引号内的文本
【发布时间】:2011-04-25 19:57:27
【问题描述】:

我正在开发一个简单的小型搜索机制,我希望允许用户搜索带有空格的文本块。例如,用户可以搜索人名:

姓名:John Smith

然后我将"John Smith".Split(' ') 放入一个包含两个元素的数组{"John","Smith"}。然后,我首先返回与“John”和“Smith”匹配的所有记录,然后返回与"John" OR "Smith." 匹配的记录,然后不返回不匹配的记录。这不是一个复杂的场景,我已经完成了这部分工作。

我现在希望能够允许用户只返回匹配“John Smith”的记录

我想使用基本的引号语法进行搜索。因此,如果用户想要搜索“John Smith”或 Pocahontas,他们将输入:“John Smith”Pocahontas。术语的顺序绝对无关紧要; “约翰·史密斯”没有优先于风中奇缘,因为他排在第一位。

关于如何解析输入,我有两个主要思路。

A) Using regular expression then parsing stuff (IndexOf, Split)
B) Using only the parsing methods 

我认为一个合乎逻辑的行动点是找到引号中的内容;然后将其从原始字符串中删除并将其插入到单独的列表中。然后从原始字符串中剩下的所有东西都可以在空间上拆分并插入到那个单独的列表中。如果有 1 个引号或奇数,则简单地将其从列表中删除。

如何在正则表达式中找到匹配项?我知道 regex.Replace,但我将如何遍历匹配并将它们插入到列表中。我知道使用 MatchEvaluator 委托和 linq 有一些巧妙的方法可以做到这一点,但我对 c# 中的正则表达式基本上一无所知。

【问题讨论】:

标签: c# regex parsing


【解决方案1】:

编辑:没有刷新就回到了这个标签,没有意识到这个问题已经被回答了......接受的答案更好。


我认为首先使用正则表达式将引号中的内容提取出来是个好主意。也许是这样的:

String sampleInput = "\"John Smith\" Pocahontas Bambi \"Jane Doe\" Aladin";

//Create regex pattern
Regex regex = new Regex("\"([^\".]+)\"");

List<string> searches = new List<string>();

//Loop through all matches from regex
foreach (Match match in regex.Matches(sampleInput))
{
    //add the match value for the 2nd group to the list
    //(1st group is the entire match)
    //(2nd group is the first parenthesis group in the defined regex pattern
    //   which in this case is the text inside the quotes)
    searches.Add(match.Groups[1].Value);
}

//remove the matches from the input
sampleInput = regex.Replace(sampleInput, String.Empty);

//split the remaining input and add the result to our searches list
searches.AddRange(sampleInput.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries));

【讨论】:

    【解决方案2】:

    我需要与 Shawn 相同的功能,但我不想使用正则表达式。这是我想出的一个简单的解决方案,它使用 Split() 而不是正则表达式,供其他需要此功能的人使用。

    之所以有效,是因为默认情况下,Split 方法将在数组中为源字符串中的连续搜索值创建空条目。如果我们对引号字符进行拆分,则结果是一个数组,其中偶数索引条目是单个单词,奇数索引条目将是引号短语。

    例子:

    “John Smith” Pocahontas
    

    结果

    item(0) = (empty string)
    item(1) = John Smith
    item(2) = Pocahontas
    

    1 2 “3 4” 5 “6 7” “8 9”
    

    结果

    item(0) = 1 2
    item(1) = 3 4
    item(2) = 5
    item(3) = 6 7
    item(4) = (empty string)
    item(5) = 8 9
    

    请注意,不匹配的引号将导致从最后一个引号到输入字符串末尾的短语。

        public static List<string> QueryToTerms(string query)
        {
            List<string> Result = new List<string>();
    
            // split on the quote token
            string[] QuoteTerms = query.Split('"');
            // switch to denote if the current loop is processing words or a phrase
            bool WordTerms = true;
    
            foreach (string Item in QuoteTerms)
            {
                if (!string.IsNullOrWhiteSpace(Item))
                    if (WordTerms)
                    {
                        // Item contains words. parse them and ignore empty entries.
                        string[] WTerms = Item.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (string WTerm in WTerms)
                            Result.Add(WTerm);
                    }
                    else
                        // Item is a phrase.
                        Result.Add(Item);
    
                // Alternate between words and phrases.
                WordTerms = !WordTerms;
            }
            return Result;
        }
    

    【讨论】:

      【解决方案3】:

      使用这样的正则表达式:

      string input = "\"John Smith\" Pocahontas";
      Regex rx = new Regex(@"(?<="")[^""]+(?="")|[^\s""]\S*");
      for (Match match = rx.Match(input); match.Success; match = match.NextMatch()) {
          // use match.Value here, it contains the string to be searched
      }
      

      【讨论】:

        猜你喜欢
        • 2015-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-16
        • 2011-12-22
        • 1970-01-01
        相关资源
        最近更新 更多