【问题标题】:Regular expression transformation for wiki-like mark-up类似 wiki 标记的正则表达式转换
【发布时间】:2009-08-28 23:32:24
【问题描述】:

考虑以下标记输入:

* 第 1 行 * 第 2 行 :* 2.1 行 :* 第 2.2 行 * 第 3 行

这通常编码为:

  • 第 1 行
  • 第 2 行
    • 2.1 行
    • 2.2 行
  • 第 3 行

我的问题:

  • 用单行表示相同的输入有什么好的表示方法?
  • 生成对应XHTML的正则表达式是什么?

例如,单行输入格式可以是:

> 1号线 > 2号线 >> 2.1号线 >> 2.2号线 > 3号线

> 是无序列表项分隔符。我选择了>,因为文本可能包含典型的标点符号。使用 »(或其他类似的非 104 键键)会很有趣,但输入起来并不容易。

行输入格式也可以是:

[第 1 行][第 2 行][第 2.1 行][第 2.2 行]][第 3 行]

更新 #1 - 问题稍微简单一些。巢的数量可以限制为三个。 n 级深度的通用解决方案仍然很酷。

更新 #2 - XHTML,而不是 HTML。

更新 #3 - 另一种可能的输入格式。

更新 #4 - 非常欢迎 Java 解决方案(或纯正则表达式)。

更新 #5

修改后的代码:

String in = " * Line 1 * Line 2 > * Line 2.1 * Line 2.2 < * Line 3";

String sub = "<ul>" + in.replace( " > ", "<ul>" ) + "</ul>";

sub = sub.replace( " < ", "</ul>" );

sub = sub.replaceAll( "( | >)\\* ([^*<>]*)", "<li>$2</li>" );

System.out.println( "Result: " + sub );

打印以下内容:

Result: <ul><li>Line 1 </li>* Line 2<ul>* Line 2.1<li>Line 2.2</li></ul>* Line 3

【问题讨论】:

  • 那么,我是否应该在回答中忽略“我的问题”上方的所有内容?这似乎是不需要的信息,因为您没有在问题中引用它。
  • "对于相同的输入,使用单行什么是好的表示?" -- 该问题是指问题顶部给出的标记输入。这可能没有必要,但我宁愿稍微多余,也不愿留下模棱两可的空间。
  • 嵌套括号,恕我直言,只会吸引具有 LISP 背景的普通用户......但我确实修复了我的答案,给出了我认为对你有用的东西。

标签: html regex xhtml wiki user-input


【解决方案1】:

我觉得你的例子很好。

 > Line 1 > Line 2 >> Line 2.1 >> Line 2.2 > Line 3

不幸的是,纯正则表达式无法跟踪您所在的嵌套级别,因此它不知道将 /UL 关闭标签放在哪里。

这样的事情可能会奏效:

 * Line 1 * Line 2 > * Line 2.1 * Line 2.2 < * Line 3

在这里,大于和小于在层次结构中上下移动,星号是项目符号的分隔符。每个之前和之后的空格都用作一种转义序列,因此当它们没有被空格包围时,您仍然可以直接使用这些字符或用于斜体和粗体等其他目的。

对正则表达式的抨击:

 string ol = "<ul>" & RegEx.Replace(t, " > ", "<ul>") & "</ul>";
 ol = RegEx.Replace(ol, " < ", "</ul>");
 ol = RegEx.Replace(ol, "( |>)\\* ([^*<>]*)", "<li>\\2</li>"); 

编辑:调整为生成 XHTML,关闭 LI 标记,基于下面的评论。还修复了我的 C# 语法。

最终编辑:我认为最后一个 Replace 中的 \ * 和 \ 2 需要为 C# 转义,修复。另外,请注意前两个 Replace() 调用可以使用 String.Replace() 而不是 RegEx,这可能会更快。

【讨论】:

  • 如果你用 "
  • \1
  • " 替换 "-([^-]*)" 你会得到有效的 xhtml
  • cobbal,是的,但该模式将替换所有连字符,而不仅仅是那些打算成为项目符号的连字符。使用连字符可能是一个糟糕的选择,因为它在英语中很常见——星号同样直观,并且更适合您的增强。
  • cobbal,我调整了我的代码以使用星号,对您的建议进行了调整,以便它可以在上面的代码中工作(需要空间或大于,因为上面的替换可能会剥离LI 字符前的空格)。
  • 【解决方案2】:

    我不建议使用正则表达式作为解析和转换工具。正则表达式往往具有很高的开销,并且不是解析语言的最有效方法......这就是你真正要求它做的事情。您已经创建了一种语言,尽管它很简单,但您应该这样对待它。我建议为您的 WIKI 样式格式代码编写一个实际的专用解析器。由于您可以将解析器专门针对您的语言,因此它应该更有效。此外,您不必创建一些可怕的怪物,即正则表达式来解析您的语言并处理其所有细微差别。从长远来看,您将获得更清晰的代码、更好的可维护性等好处。

    我建议以下资源:

    【讨论】:

    • 我明白了。正则表达式是一种可能性,但是,我不确定是否真的能满足您的需求。鹿茸可能仍然有帮助。它是一个解析器生成器,而且你的语法看起来相当简单。即使它是一次性的,您仍然可以使用 ANTLER 生成解析器,并编写一个简单的 C# 程序来执行转换,所用时间比找出 RegEx 所需的时间还短。 ;)
    • ANTLR 也可用于 Java,但如果您能够在 6 分钟内创建 RegEx 版本,那么我同意,ANTLR 已经出局。 :P
    【解决方案3】:

    解决方案

    一个可行的解决方案如下:

    public class Test {
      public Test() {
      }
    
      public static void main( String[] args ) {
        String in = "= Line 1 = Line 2 > = Line 2.1 = Line 2.2 < = Line 3";
    
        in = in.replaceAll( "= ([^=<>]*)", "<li>$1</li>" );
        in = in.replace( ">> ", "><ul>" );
        in = in.replace( ">< ", "></ul>" );
        in = "<ul>" + in + "</ul>";
        System.out.println( in );
      }
    }
    

    这将创建所需的 XHTML 片段:

    <ul><li>Line 1 </li><li>Line 2 </li><ul><li>Line 2.1 </li><li>Line 2.2 </li></ul><li>Line 3</li></ul>
    

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签