正则表达式示例:Wiki 解析程序

Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本

这个简单的 Wiki 文本转换示例说明了正则表达式的一些用途:

  • 将与源 Wiki 模式匹配的文本行转换为相应的 HTML 输出字符串。

  • 使用正则表达式将 URL 模式转换为 HTML <a> 超链接标签。

  • 使用正则表达式将美元符号字符串(如 "$9.95")转换为欧元符号字符串(如 "8.24 €")。

若要获取此示例的应用程序文件,请参阅 www.adobe.com/go/learn_programmingAS3samples_flash_cn。WikiEditor 应用程序文件位于文件夹 Samples/WikiEditor 中。该应用程序包含以下文件:

文件

说明

WikiEditor.mxml

WikiEditor.fla

Flash 或 Flex 中的主应用程序文件(分别为 FLA 和 MXML)。

com/example/programmingas3/regExpExamples/WikiParser.as

该类包含使用正则表达式将 Wiki 输入文本模式转换为等效 HTML 输出的方法。

com/example/programmingas3/regExpExamples/URLParser.as

该类包含使用正则表达式将 URL 字符串转换为 HTML <a> 超链接标签的方法。

com/example/programmingas3/regExpExamples/CurrencyConverter.as

该类包含使用正则表达式将美元符号字符串转换为欧元符号字符串的方法。

定义 WikiParser 类

WikiParser 类包含将 Wiki 输入文本转换为等效 HTML 输出的方法。它虽然不是功能非常强大的 Wiki 转换应用程序,但是说明了正则表达式在模式匹配和字符串转换方面的一些很好的用法。

构造函数和 setWikiData() 方法一起,可简单地初始化 Wiki 输入文本范例字符串,如下所示:

public function WikiParser() 
{ 
    wikiData = setWikiData(); 
}

当用户单击范例应用程序中的“Test”按钮时,应用程序将调用 WikiParser 对象的 parseWikiString() 方法。此方法可调用许多其他方法,这些方法再组合输出的 HTML 字符串。

public function parseWikiString(wikiString:String):String 
{ 
    var result:String = parseBold(wikiString); 
    result = parseItalic(result); 
    result = linesToParagraphs(result); 
    result = parseBullets(result); 
    return result; 
}

所调用的每个方法(parseBold()parseItalic()linesToParagraphs()parseBullets())都会使用字符串的 replace() 方法替换由正则表达式定义的匹配模式,以便将 Wiki 输入文本转换为 HTML 格式的文本。

转换粗体和斜体模式。

parseBold() 方法会查找 Wiki 粗体文本模式(如 '''foo''')并将其转换为等效的 HTML 格式(如 <b>foo</b>),如下所示:

private function parseBold(input:String):String 
{ 
    var pattern:RegExp = /'''(.*?)'''/g; 
    return input.replace(pattern, "<b>$1</b>"); 
}

请注意,正则表达式的 (.?*) 部分匹配两个定义 ''' 模式之间任意数目的字符 (*)。? 数量表示符使匹配不再是无限制的,因此对于字符串 '''aaa''' bbb '''ccc''',第一个匹配的字符串是 '''aaa''' 而不是以 ''' 模式开头和结尾的整个字符串。

正则表达式中的括号定义捕获组,replace() 方法通过在替换字符串中使用 $1 代码引用此组。正则表达式中的 g (global) 标志确保 replace() 方法替换字符串中的所有匹配(不仅仅是第一个)。

parseItalic() 方法的原理与 parseBold() 方法类似,只是前者检查作为斜体文本分隔符的两个省略号 ('')(而不是三个):

private function parseItalic(input:String):String 
{ 
    var pattern:RegExp = /''(.*?)''/g; 
    return input.replace(pattern, "<i>$1</i>"); 
}

转换项目符号模式

如下面的示例所示,parseBullet() 方法会查找 Wiki 项目符号行模式(如 * foo)并将其转换为等效的 HTML 格式(如 <li>foo</li>):

private function parseBullets(input:String):String 
{ 
    var pattern:RegExp = /^\*(.*)/gm; 
    return input.replace(pattern, "<li>$1</li>"); 
}

正则表达式开头的 ^ 符号匹配行的开头。正则表达式中的 m (multiline) 标志使正则表达式用 ^ 符号来匹配行的开头,而不是简单地匹配字符串的开头。

\* 模式匹配星号字符(反斜杠用于表示星号本身,而不是 * 数量表示符)。

正则表达式中的括号定义捕获组,replace() 方法通过在替换字符串中使用 $1 代码引用此组。正则表达式中的 g (global) 标志确保 replace() 方法替换字符串中的所有匹配(不仅仅是第一个)。

转换段落 Wiki 模式

linesToParagraphs() 方法将每行中输入的 Wiki 字符串转换为 HTML <p> 段落标签。该方法中的这些行从输入的 Wiki 字符串中去除空行:

var pattern:RegExp = /^$/gm; 
var result:String = input.replace(pattern, "");

正则表达式中的 ^$ 符号分别匹配行的开头和结尾。正则表达式中的 m (multiline) 标志使正则表达式用 ^ 符号来匹配行的开头,而不是简单地匹配字符串的开头。

replace() 方法使用空字符串 ("") 替换所有匹配子字符串(空行)。正则表达式中的 g (global) 标志确保 replace() 方法替换字符串中的所有匹配(不仅仅是第一个)。

将 URL 转换为 HTML <a> 标签

当用户单击范例应用程序中的“Test”按钮时,如果用户选中了 urlToATag 复选框,应用程序将调用 URLParser.urlToATag() 静态方法以将 URL 字符串从输入的 Wiki 字符串转换为 HTML <a> 标签。

var protocol:String = "((?:http|ftp)://)"; 
var urlPart:String = "([a-z0-9_-]+\.[a-z0-9_-]+)"; 
var optionalUrlPart:String = "(\.[a-z0-9_-]*)"; 
var urlPattern:RegExp = new RegExp(protocol + urlPart + optionalUrlPart, "ig"); 
var result:String = input.replace(urlPattern, "<a href='$1$2$3'><u>$1$2$3</u></a>");

RegExp() 构造函数用于将各组成部分组合成正则表达式 (urlPattern)。这些组成部分是定义正则表达式模式部分的各个字符串。

protocol 字符串定义的正则表达式模式的第一部分定义了 URL 协议:http:// ftp://。括号定义了由 ? 符号表示的非捕获组。这意味着括号只是用来定义用于 | 逻辑“或”模式的组,该组不会匹配 replace() 方法的替换字符串中的逆向引用代码($1$2$3)。

正则表达式的其他组成部分都会使用捕获组(由模式中的括号表示),然后用在 replace() 方法的替换字符串中的逆向引用代码($1$2$3)中。

urlPart 字符串定义的模式部分至少匹配下列字符中的一个:a-z0-9_-+ 数量表示符表明至少一个字符匹配。\。 表示一个必需的点 (.) 字符。其余部分匹配至少包含以下字符中的一个的字符串:a-z0-9_-

optionalUrlPart 字符串定义的模式部分匹配零个或多个以下字符:点 (.) 字符后跟任意数目的字母数字字符(包括 _-)。* 数量表示符表明零个或多个字符匹配。

调用 replace() 方法可应用正则表达式,并且使用逆向引用来组合替换 HTML 字符串。

然后 urlToATag() 方法会调用 emailToATag() 方法,后者使用类似的技术用 HTML <a> 超链接字符串替换电子邮件模式。在本范例文件中用于匹配 HTTP、FTP 和电子邮件 URL 的正则表达式是相当简单的,只是起到示范作用,还有更复杂的正则表达式更准确地匹配这类 URL。

将美元符号字符串转换为欧元符号字符串

当用户单击范例应用程序中的“Test”按钮时,如果用户选中了 dollarToEuro 复选框,应用程序将调用 CurrencyConverter.usdToEuro() 静态方法以将美元符号字符串(如 "$9.95")转换为欧元符号字符串(如 "8.24 €"),如下所示:

var usdPrice:RegExp = /\$([\d,]+.\d+)+/g; 
return input.replace(usdPrice, usdStrToEuroStr); 

第一行定义的简单模式匹配美元符号字符串。请注意,$ 字符前面加反斜杠 (\) 转义字符。

replace() 方法将正则表达式用作模式匹配参数,并调用 usdStrToEuroStr() 函数以确定替换字符串(欧元值)。

如果将函数名称用作 replace() 方法的第二个参数时,则会将以下内容作为参数传递给被调用的函数:

  • 字符串的匹配部分。

  • 任何捕获的括号组匹配。按这种方式传递的参数数目因捕获的括号组匹配的数目而异。您可以通过检查函数代码中的 arguments.length - 3 来确定捕获的括号组匹配的数目。

  • 字符串中匹配开始的索引位置。

  • 完整的字符串。

usdStrToEuroStr() 方法将美元符号字符串模式转换为欧元符号字符串,如下所示:

private function usdToEuro(...args):String 
{ 
    var usd:String = args[1]; 
    usd = usd.replace(",", ""); 
    var exchangeRate:Number = 0.828017; 
    var euro:Number = Number(usd) * exchangeRate; 
    trace(usd, Number(usd), euro); 
    const euroSymbol:String = String.fromCharCode(8364); // € 
    return euro.toFixed(2) + " " + euroSymbol;  
}

请注意,args[1] 表示由 usdPrice 正则表达式匹配的捕获括号组。这是美元符号字符串的数字部分,也就是没有 $ 符号的美元数目。该方法应用汇率转换并返回生成的字符串(带有尾随符号 €,而不是前导符号 $)。