【问题标题】:replace string regex替换字符串正则表达式
【发布时间】:2012-05-12 09:08:01
【问题描述】:

我试图让用户能够在 CMS 中使用一些额外的“标签”“标记”某些内容部分,如果您愿意,这些部分会在内容呈现时被翻译,例如粗体页面。

类似于{strong:Lorum ipsum dolar} 的内容,然后将使用<strong>Lorum ipsum dolar</strong> 包裹文本。

我试图为此找出正则表达式,但我不好。我从网站上抓取了一些 html 替换脚本,它们不是很有帮助,至少,我不知道要更改什么:$。

任何帮助将不胜感激。

注意

我在 C# 中这样做。

【问题讨论】:

  • 你想用什么语言来实现正则表达式? php?
  • 这似乎会带来整个世界的无效标签问题。
  • $str = q({strong:Lorum ipsum dolar}); $str =~ m/\{(\w+):(.+?)\}/; $str = "<$1>$2</$1>"; 糟糕的解决方案,但有效(perl)
  • @loldop:除非并且直到他们开始嵌套这些东西,如{strong:Lor{i:e}m ipsum dol{i:o}r}。使用 Perl 对正则表达式的扩展,这甚至是可能的——在“纯”正则表达式中,您只能在某个预定的嵌套深度内进行。
  • 与其重新发明轮子,为什么不让他们编写 HTML 并禁止某些标签或使用 BBCode?已经有很多可用的解析选项和一些用于 HTML 和 BBCode 的 WYSIWYG 编辑器。

标签: c# html regex


【解决方案1】:

这看起来很像 json 到 XML 的转换。

{"strong":"Lorum ipsum dolar"} 

会变成

<strong>Lorum ipsum dolar</strong>

{"strong":{italic:"Lorum ipsum dolar"}}

会变成

<strong>
<italic>Lorum ipsum dolar</italic>
</strong>

我并不是说这就是答案,但您可能想看一下。基本思想是将您的标签解析为分层结构,然后将其解析回 HTML 或您使用的任何输出语言。

【讨论】:

    【解决方案2】:

    所以这将为您提供您正在寻找的标签和部分,但是,我将这些结果转换为最终字符串的方式非常难看。它实际上只是最重要的正则表达式。享受吧!

    string test = "{strong:lorem ip{i:su{b:m}m}m dolar} {strong:so strong}";
    Regex tagParse = new Regex(
        @"\{(?<outerTag>\w*)
            (?>
                (?<DEPTH>\{(?<innerTags>\w*))
                |
                (?<-DEPTH>\})
                |
                :?(?<innerContent>[^\{\}]*)
            )*
            (?(DEPTH)(?!))
    
            ", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
    
    MatchCollection matches = tagParse.Matches(test);
    foreach (Match m in matches)
    {
        StringBuilder sb = new StringBuilder();
        List<string> tags = new List<string>();
        tags.Add(m.Groups["outerTag"].Value);
        foreach (Capture c in m.Groups["innerTags"].Captures)
            tags.Add(c.Value);
        List<string> content = new List<string>();
        foreach (Capture c in m.Groups["innerContent"].Captures)
            content.Add(c.Value);
        if (tags.Count > 1)
        {
            for (int i = 0; i < content.Count; i++)
            {
                if (i >= tags.Count)
                    sb.Append("</" + tags[tags.Count - (i - tags.Count + 1)] + ">");
                else
                    sb.Append("<" + tags[i] + ">");
                sb.Append(content[i]);
            }
            sb.Append("</" + tags[1] + ">");
        }
        else
        {
            sb.Append("<" + tags[0] + ">");
            sb.Append(content[0]);
        }
        sb.Append(m.Groups["outerContent"].Value);
        sb.Append("</" + m.Groups["outerTag"].Value + ">");
        Console.WriteLine(sb.ToString());
    }  
    

    【讨论】:

      【解决方案3】:

      编辑:要使用嵌套标签,每个输入字符串有多个匹配项。 限制:标签对内的文本不能包含“{”或“}”。

      private string FormatInput(string input)
      {
          const string patternNonGreedy = @"\{(?<tag>.+?):(\s*)(?<content>.*?)(\s*)}";
          const string patternGreedy = @"\{(?<tag>.+?):(\s*)(?<content>.*)(\s*)}";
      
          Match mtc = Regex.Match(input, patternGreedy);
          if (!mtc.Success)
              return input;
      
          string content = mtc.Groups["content"].Value;
          int braces = 0;
          foreach (char c in content)
          {
              if (c == '{')
                  braces++;
              else if (c == '}')
              {
                  if (braces > 0)
                      braces--;
              }
          }
      
          if (braces == 0)
              return input.Substring(0, mtc.Index)
                  + string.Format("<{0}>{1}</{0}>", mtc.Groups["tag"].Value, FormatInput(content))
                  + input.Substring(mtc.Index + mtc.Length);
      
          mtc = Regex.Match(input, patternNonGreedy);
          Debug.Assert(mtc.Success);
      
          content = mtc.Groups["content"].Value;
          return input.Substring(0, mtc.Index)
              + string.Format("<{0}>{1}</{0}>", mtc.Groups["tag"].Value, content)
              + FormatInput(input.Substring(mtc.Index + mtc.Length));
      }
      

      测试示例:

      string output1 = FormatInput("{strong:Lorum ipsum dolar}");
      // output1: <strong>Lorum ipsum dolar</strong>
      
      string output2 = FormatInput("{strong:{italic:Lorum ipsum dolar}}");
      // output2: <strong><italic>Lorum ipsum dolar</italic></strong>
      
      string output3 = FormatInput("{strong:Lor{i:e}m ipsum dol{i:o}r}");
      // output3: <strong>Lor<i>e</i>m ipsum dol<i>o</i>r</strong>
      

      【讨论】:

      • 这与 Christopher Creutzig 早期指出的缺点相同。它不处理嵌套标签。
      • @FlyingStreudel 感谢您指出这一点。我已经更新了它并使用递归方法和非贪婪的正则表达式匹配来解决这个问题。
      猜你喜欢
      • 2018-07-13
      • 2017-02-04
      • 1970-01-01
      • 2015-11-30
      • 2021-11-29
      • 2018-04-06
      • 2014-08-25
      相关资源
      最近更新 更多