簡體   English   中英

將Perl正則表達式轉換為等效的ECMAScript正則表達式

[英]Convert Perl regular expression to equivalent ECMAScript regular expression

現在,我使用的是VC ++ 2010,但是VC ++ 2010的syntax_option_type僅包含以下選項:

static const flag_type icase = regex_constants::icase;
static const flag_type nosubs = regex_constants::nosubs;
static const flag_type optimize = regex_constants::optimize;
static const flag_type collate = regex_constants::collate;
static const flag_type ECMAScript = regex_constants::ECMAScript;
static const flag_type basic = regex_constants::basic;
static const flag_type extended = regex_constants::extended;
static const flag_type awk = regex_constants::awk;
static const flag_type grep = regex_constants::grep;
static const flag_type egrep = regex_constants::egrep;

它不包含perl_syntax_group(Boost庫具有此選項)。 但是,我不想使用Boost庫。

Perl中有許多正則表達式,因此,我想將現有的Perl正則表達式轉換為ECMAScript (或VC ++ 2010支持的任何正則表達式)。 轉換后,我可以直接在VC ++ 2010中使用等效的正則表達式,而無需使用第三方libray。

一個例子:

const boost::tregex e(__T("\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z"));
const CString human_format = __T("$1-$2-$3-$4");
CString human_readable_card_number(const CString& s)
{
   return boost::regex_replace(s, e, human_format);
}
CString credit_card_number = "1234567887654321";
credit_card_number = human_readable_card_number(credit_card_number);
assert(credit_card_number == "1234-5678-8765-4321");

在上面的示例中,我想做的是將eformat轉換為ECMAScript樣式表達式。

是否可以找到將所有Perl正則表達式轉換為ECMAScript樣式的通用方法? 有一些工具可以做到這一點嗎?

任何幫助將不勝感激!

對於要轉換的特定正則表達式,ECMA正則表達式中的等效項為:

/^(\d{3,4})[- ]?(\d{4})[- ]?(\d{4})[- ]?(\d{4})$/

在這種情況下, \\A (在Perl regex中)的含義與^ (在ECMA regex中)(匹配字符串的開頭)相同, \\Z (在Perl regex中)與$ (在ECMA regex中)相同的含義(匹配字符串的結尾)。 請注意,如果啟用多行模式,則ECMA正則表達式中^$含義將更改為與行的開頭和結尾匹配。

ECMA regex是Perl regex的子集,因此,如果該regex使用Perl regex中的專有功能,則可能無法轉換為ECMA regex。 即使對於相同的語法,該語法在正則表達式的兩個方言之間可能意味着稍有不同,因此檢查文檔並比較用法總是明智的。

我只想說說ECMA regex和Perl regex有何相似之處。 什么不是相似但可轉換,我將盡我所能提起。

ECMA正則表達式缺少與Unicode一起使用的功能,這些功能迫使您查找代碼點並將其指定為字符類。

按照有關Perl正則表達式文檔進行操作

  • 修飾符:
    • ECMA標准中只有igm ,它們的行為與Perl中的相同。
    • s dot-all修飾符可以在ECMA正則表達式中通過使用2個補碼字符類來模擬,例如[\\S\\s][\\D\\d]
    • 無論如何,不​​支持xp標志。
    • 我不知道是否還有其他模擬方式(前綴和后綴修飾符)。
  • 元字符:
    • 對於將\\與非元字符結合使用並不能解決任何特殊含義,我有些懷疑,但是如果您不逃避不需要的地方就沒問題了。 . 在ECMA中,排除了另外幾個字符。 其余的在ECMA正則表達式中表現相同(甚至m標志對^$ )。
  • 量詞:
    • 貪婪和懶惰的行為應該是相同的。 ECMA正則表達式中沒有所有格行為。
  • 轉義序列:
    • ECMA正則表達式中沒有\\a\\e \\t\\n\\r\\f相同。
    • 如果正則表達式具有\\cX請檢查文檔-有所不同。
    • \\xhh在ECMA regex和Perl regex中很常見(指定2個十六進制數字是最安全的-否則,您將必須查閱文檔以查看該語言如何處理少於2個十六進制數字的情況)。
    • \\uhhhh是ECMA regex 專有功能,用於指定Unicode字符。 Perl還有其他專用的字符指定方式,例如\\x{}\\N{}\\o{}\\000
    • \\l\\u\u003c/code> , \\L\\U是Perl regex 專有的
    • 可以通過手動轉引引用的部分來模擬\\Q\\E
    • Perl正則表達式中的八進制轉義符(少於3個八進制數字)可能會造成混淆。 仔細檢查上下文,閱讀文檔和/或測試正則表達式以確保您了解它在上下文中的作用,因為它可能是轉義序列或向后引用。
  • 角色類和其他特殊轉義符:
    • 如果采用US-ASCII,則\\w\\W\\s\\S\\d\\D在ECMA regex和Perl regex中是等效的。 如果涉及Unicode,事情將變得一團糟。
    • ECMA正則表達式中沒有POSIX字符類。 使用上面的\\w\\s\\d或在角色類中指定自己。
    • 反向引用基本相同-但我不知道它是否允許Perl和ECMA regex的反向引用都超過9。
    • 可以使用反向參考來模擬命名參考。
    • ECMA regex不支持其余的( []和已提及的轉義序列除外)。
  • 斷言:
    • 關於如何基於\\w定義\\b\\B在兩種語言中都是等效的。
  • 捕獲組:分組()和反向引用相同。 $n (在替換字符串中用於反向引用匹配的文本)是相同的。 本節中的其余部分是Perl獨有的功能。
  • 引用元字符:(前面部分中已經提到的內容)。
  • 擴展模式:
    • ECMA regex不支持在regex內部修改標志。 根據標志的不同,您可能可以重寫正則表達式( s標志是始終可以在ECMA regex中轉換為等效表達式s標志)。
    • 在Perl和ECMA之間,只有(?:pattern) (非捕獲組), (?=pattern) (正視), (?!pattern) (負視)是常見的。
    • ECMA正則表達式中沒有注釋,因此(?#text)可以忽略。
    • ECMA正則表達式不支持向后看。 Perl支持固定寬度的向后搜索。 在某些情況下,通過在捕獲組后面進行查找,可以將用Perl編寫的具有正向外觀的正則表達式轉換為ECMA正則表達式。
    • 如前所述,命名模式可以轉換為正常捕獲組,並可以用編號的反向引用進行引用。
    • 其余是Perl獨有的功能。
  • 特殊的回溯控制動詞:這是Perl獨有的,我不知道它們的作用(以前從未接觸過它們),更不用說轉換了。 最有可能的是它們無論如何都不能轉換。

結論

如果正則表達式可以充分利用Perl正則表達式的功能,或者在Boost庫支持的級別(例如,遞歸正則表達式)使用,則無法將正則表達式轉換為ECMA正則表達式。 幸運的是,ECMA正則表達式涵蓋了最常用的功能,因此正則表達式很可能是可轉換的。

參考

有關MDN的ECMA RegExp參考

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM