现代 ABAP 编程语言中的正则表达式
在這篇博文中,我想分享現(xiàn)代 ABAP 中正則表達(dá)式的最新消息和變化,主要來自 OP 版本 7.55 和 7.56。
以前,在 ABAP 中使用 POSIX 樣式的正則表達(dá)式或“uniX 的便攜式操作系統(tǒng)接口- POSIX 的全稱是 Portable Operating System Interface for uniX”。 因此,從現(xiàn)在開始,POSIX 語法中的正則表達(dá)式已過時(shí),然后使用這種正則表達(dá)式語法會(huì)導(dǎo)致語法檢查警告。 雖然這可以被 pragma ##regex_posix 隱藏,但強(qiáng)烈建議遷移到 ABAP 支持的其他正則表達(dá)式語法,如 PCRE 正則表達(dá)式、XPath 正則表達(dá)式或 XSD 正則表達(dá)式。
ABAP 正則表達(dá)式的回顧
正則表達(dá)式對(duì)于新用戶來說通常是復(fù)雜和令人生畏的。 在深入研究新功能之前,我想簡要介紹一下 RegEx,并展示用 ABAP 明確編寫的示例。 如果您是該主題的專家并且可能會(huì)感到無聊,請(qǐng)隨時(shí)跳過此部分。
RegEx 的概念已經(jīng)存在了很長一段時(shí)間。當(dāng)需要復(fù)雜的模式時(shí)使用它。 如搜索數(shù)字、字母、特殊字符或驗(yàn)證電子郵件等。許多文本搜索和替換問題在不使用正則表達(dá)式模式匹配的情況下很難處理。 此外,在 ABAP 中,使用正則表達(dá)式的搜索比傳統(tǒng)的 SAP 模式更強(qiáng)大。讓我們以這個(gè)簡單的例子為例:
FIND 'A' IN 'ABCD1234EFG'MATCH COUNT sy-tabix.WRITE: sy-tabix.現(xiàn)在,如果您想在不使用 RegEx 的情況下通過正常搜索模式查找字符串中的所有字母,則需要對(duì)所有 26 個(gè)字符進(jìn)行循環(huán)。 使用 RegEx,可以很容易地搜索和找到所有七個(gè)字符:
FIND ALL OCCURRENCES OF PCRE '[A-Z]' IN 'ABCD1234EFG'MATCH COUNT sy-tabix. WRITE: sy-tabix.ABAP 在語句 FIND 和 REPLACE 中以及通過類 CL_ABAP_REGEX 和 CL_ABAP_MATCHER 支持正則表達(dá)式。 CL_ABAP_MATCHER 類將使用 CL_ABAP_REGEX 生成的正則表達(dá)式應(yīng)用于字符串或內(nèi)部表。
Greedy or Lazy?
另一個(gè)可能有趣的概念是 RegEx 中貪婪或惰性量詞的含義。 在用 (,+,…) 定義的貪婪模式中,量化字符被重復(fù)盡可能多的次數(shù)。 RegEx 引擎將盡可能多的字符添加到匹配中,然后一個(gè)一個(gè)地縮短,以防模式的其余部分不匹配。 它的反面將被稱為懶惰模式,它匹配盡可能少的字符。 例如,在 ABAP 中,通過在 * , (.?) 后面放置一個(gè)問號(hào),您要求子表達(dá)式匹配盡可能少的字符。 正則表達(dá)式的默認(rèn)行為是貪婪的(實(shí)際上 POSIX 意味著無法關(guān)閉的貪婪量詞)。
例子:
DATA(text) = `"Jack" and "Jill" went up the "hill"`.FIND ALL OCCURRENCES OF PCRE `"(.*?)"` IN text IGNORING CASERESULTS DATA(result_tab). IF sy-subrc = 0.LOOP AT result_tab ASSIGNING FIELD-SYMBOL(<result>).cl_demo_output=>write( substring( val = text off = <result>-offset len = <result>-length ) ).ENDLOOP. ENDIF. cl_demo_output=>display( ).貪婪符號(hào)“(.)”將整個(gè)輸入句子作為輸出,而懶惰符號(hào)“(.?)”給出三個(gè)單詞“Jack”、“Jill”、“hill”。 如果在懶惰的情況下省略表達(dá)式“ALL OCCURRENCES OF”,則只會(huì)找到第一個(gè)“和后面的”之間的子字符串,即“Jack”。
直到 7.55 版本,ABAP 僅將 POSIX 庫用于 RegEx。 從那時(shí)起,也支持 Perl 庫。 兩個(gè)庫在計(jì)算匹配的方式上有很大不同。 由于 POSIX 已經(jīng)過時(shí),我們將在下文中使用 Perl 風(fēng)格的正則表達(dá)式。 您可以通過在 AS ABAP 中運(yùn)行報(bào)表 DEMO_REGEX 來嘗試使用 Regex 來嘗試不同的表達(dá)式。
PCRE Syntax
PCRE 庫是一組用 C 語言編寫的函數(shù),它們使用與 Perl 5 相同的語法和語義實(shí)現(xiàn)正則表達(dá)式模式匹配,并擁有自己的原生 API。 PCRE 語法代表“Perl Compatible Regular Expressions”,比 POSIX 語法或許多其他正則表達(dá)式庫更強(qiáng)大、更靈活,并且比 ABAP 支持的 POSIX 正則表達(dá)式性能更好。
具有 PCRE 語法的 RegEx 可以在 FIND 和 REPLACE 語句的添加 PCRE 和字符串的內(nèi)置函數(shù)的參數(shù) PCRE 之后指定。 PCRE 正則表達(dá)式的對(duì)象可以使用系統(tǒng)類 CL_ABAP_REGEX 的工廠方法 CREATE_PCRE 創(chuàng)建,用于語句 FIND 和 REPLACE 或使用系統(tǒng)類 CL_ABAP_MATCHER。
例子:
DATA(text) = `oooababboo`.FIND PCRE 'a.|[ab]+|b.*' IN textMATCH OFFSET DATA(moff)MATCH LENGTH DATA(mlen). IF sy-subrc = 0.cl_demo_output=>write( substring( val = text off = moff len = mlen ) ). ENDIF.搜索使用 PCRE 正則表達(dá)式語法并從偏移量 3 中找到長度為 2 的“ab”。但是,使用加法 REGEX 而不是 PCRE,搜索會(huì)從偏移量 3 或更高的長度為 5 中找到子字符串“abbabb”。
Callouts in PCRE Regular Expressions
通過RegEx callouts,可以在正則表達(dá)式模式匹配過程中臨時(shí)將控制權(quán)交給函數(shù)。 PCRE 標(biāo)注使用語法 (?C…) 指定,其中點(diǎn)代表可選參數(shù)。如果你在調(diào)用 PCRE 的匹配函數(shù)之前指定一個(gè) callout 函數(shù),每當(dāng)引擎運(yùn)行到 (?C…) 時(shí),它會(huì)暫時(shí)掛起匹配并將控制權(quán)傳遞給那個(gè) callout 函數(shù),它提供有關(guān)匹配的信息。然后調(diào)用函數(shù)執(zhí)行它應(yīng)該做的任何任務(wù),然后它向引擎返回一個(gè)代碼,讓它知道是否正常進(jìn)行剩下的比賽。
在 ABAP 中,PCRE 語法支持在將正則表達(dá)式與 CL_ABAP_MATCHER 匹配期間調(diào)用 ABAP 方法的標(biāo)注。當(dāng)執(zhí)行方法 MATCH 時(shí),PCRE 正則表達(dá)式的特殊字符 (?C…) 然后調(diào)用接口方法 CALLOUT。該示例演示了如何從 PCRE 正則表達(dá)式調(diào)用 ABAP 方法。
REPORT demo_pcre_callout.CLASS handle_regex DEFINITION.PUBLIC SECTION.INTERFACES if_abap_matcher_callout. ENDCLASS.CLASS handle_regex IMPLEMENTATION.METHOD if_abap_matcher_callout~callout.cl_demo_output=>write( |{ callout_num } { callout_string }| ).ENDMETHOD. ENDCLASS.CLASS demo_pcre DEFINITION.PUBLIC SECTION.CLASS-METHODS main. ENDCLASS.CLASS demo_pcre IMPLEMENTATION.METHOD main.DATA(regex) = cl_abap_regex=>create_pcre(pattern = `a(?C1)b(?C2)c(?C3)d(?C"D")e(?C"E")` ).DATA(matcher) = regex->create_matcher( text = `abcde` ).DATA(handler) = NEW handle_regex( ).matcher->set_callout( handler ).matcher->match( ).cl_demo_output=>display( ).ENDMETHOD. ENDCLASS.START-OF-SELECTION.demo_pcre=>main( ).正則表達(dá)式包含用于標(biāo)注的特殊字符 (?C…)。 前三個(gè)標(biāo)注傳遞數(shù)字?jǐn)?shù)據(jù),其他兩個(gè)傳遞字符串?dāng)?shù)據(jù)。
本地類“handle_regex”實(shí)現(xiàn)接口 IF_ABAP_MATCHER_CALLOUT 并且該類的實(shí)例被設(shè)置為標(biāo)注處理程序。 當(dāng)正則表達(dá)式匹配到時(shí),每個(gè)callout位置都會(huì)調(diào)用接口方法CALLOUT,可以訪問傳入的參數(shù)。
PCRE syntax for ABAP SQL and ABAP CDS
ABAP SQL 和 ABAP CDS 還通過內(nèi)置函數(shù) REPLACE_REGEXPR、LIKE_REGEXPR 和 OCCURRENCES_REGEXPR 支持 PCRE 語法。 這些函數(shù)訪問在 SAP HANA 數(shù)據(jù)庫中實(shí)現(xiàn)的 PCRE1 庫。 一般 ABAP 的正則表達(dá)式與 ABAP 內(nèi)核中實(shí)現(xiàn)的 PCRE2 庫一起使用。
CDS View Entity
此 SQL 函數(shù)在字符串中搜索正則表達(dá)式模式,并返回該字符串,其中包含使用 CDS 視圖實(shí)體中的替換字符串替換的正則表達(dá)式模式的一次或每次出現(xiàn)。
REPLACE_REGEXPR(PCRE => pcre,VALUE => arg1,WITH => arg2,RESULT_LENGTH => res[,OCCURRENCE => occ][,CASE_SENSITIVE => case][,SINGLE_LINE => bool][,MULTI_LINE => bool][,UNGREEDY => bool])以下 CDS 視圖實(shí)體將 SELECT 列表中的字符串的內(nèi)置 SQL 函數(shù)應(yīng)用于 DDIC 數(shù)據(jù)庫表 SPFLI 的列,以使用轉(zhuǎn)換值替換 MI 到 KM 的距離 id。
@AccessControl.authorizationCheck: #NOT_REQUIREDdefine view entity ZI_regex_testas select from spfli{concat_with_space( cityfrom, cityto, 4 ) as from_City_to,distance as Distance,distid as DistanceId,casewhen distid = 'MI' thenreplace_regexpr( pcre => '[^<]+',value => distid,with => '1.6 KM',result_length => 6 )else 'KM'end as DistanceIdInKM}SQL Expressions
ABAP SQL 現(xiàn)在支持一些新的正則處理功能。
本示例從 spfli 表中選擇來自柏林或東京的航班,并將它們放在 lt_table 中。
SELECT * FROM spfliWHERElike_regexpr( pcre = '\bBERLIN\b|\bTOKYO\b', value = cityfrom ) = '1'INTO @ls_table.APPEND ls_table TO lt_table. ENDSELECT.以下示例使用正則表達(dá)式替換從東京到 Neapel 的航班的目的地“羅馬”。
SELECTcarrid as Airline,connid as flightNo,deptime as Departure_time,cityfrom as Departure,replace_regexpr( pcre = '\bROME\b', value = cityto , with = 'Neapel' ) as Destinationfrom spfli where cityfrom = 'TOKYO' into TABLE @data(lt_replace) .并非所有可以為 ABAP CDS 視圖實(shí)體(例如 UNGREEDY)中的 REPLACE_REGEXPR 函數(shù)指定的參數(shù)也可以為 ABAP SQL 指定。 此功能可以通過 PCRE 語法本身來實(shí)現(xiàn)。
Xpath and XSD Syntax
功能豐富的 PCRE 正則表達(dá)式幾乎可以在所有情況下使用。然而,Perl 使用的正則表達(dá)式查詢并不能很好地將 XML/HTML 分解成有意義的部分并輕松解析它們。為了解決這個(gè)難題,ABAP 還支持 Xpath & XSD 正則表達(dá)式,并在內(nèi)部將其轉(zhuǎn)換為 PCRE 語法。
XPath 代表“XML 路徑語言”,是一種用于指定 XML 文檔部分的表達(dá)式語言。 XPath 也可用于結(jié)構(gòu)類似于 XML 的文檔,如 HTML。 XPath 語法中的正則表達(dá)式可以在正常和擴(kuò)展模式下編譯。在擴(kuò)展模式下,模式的大多數(shù)未轉(zhuǎn)義空格(空格和換行符)在字符類之外被忽略,注釋可以放在 # 后面。在ABAP內(nèi)置函數(shù)中,擴(kuò)展模式默認(rèn)開啟,可以通過正則表達(dá)式中的(?-x)關(guān)閉。
與正則表達(dá)式不同,我們?cè)谑褂?XPath 時(shí)不需要提前知道數(shù)據(jù)的模式。由于 XML 文檔是使用節(jié)點(diǎn)結(jié)構(gòu)化的,XPath 使用該結(jié)構(gòu)來瀏覽節(jié)點(diǎn)以返回包含我們正在尋找的節(jié)點(diǎn)的對(duì)象。
例子:XPath 正則表達(dá)式的一個(gè)特殊功能是字符集的減法。 在以下示例中,從字符集 BasicLatin 中減去字母 a 到 c,第一個(gè)匹配項(xiàng)是偏移量為 3 的 d。
FIND REGEXcl_abap_regex=>create_xpath2( pattern = '[\p{IsBasicLatin}-[a-c]]' )IN 'abcd' MATCH OFFSET DATA(moff).與 PCRE 相比,XPath 正則表達(dá)式允許轉(zhuǎn)義字符 \ 而不僅僅是在特殊字符前面。 在以下示例中,帶有參數(shù) xpath 的 match 函數(shù)會(huì)找到 x,而帶有參數(shù) pcre 的 match 函數(shù)則不會(huì)。 因此,第一個(gè) FIND 語句在 sy-subrc 中返回值 0,而第二個(gè) FIND 語句返回 4。
DATA(x) = match( val = `abxcd` xpath = `\x` occ = 1 ). DATA(y) = match( val = `abxcd` pcre = `\x` occ = 1 ).FIND REGEX cl_abap_regex=>create_xpath2( pattern = '\x' ) IN 'abxcd'. FIND REGEX cl_abap_regex=>create_pcre( pattern = '\x' ) IN 'abxcd'.XSD Syntax
XSD 代表“Xml Schema Definition”,是 XPath 語法的一個(gè)子集。與其他正則表達(dá)式相比,XML 模式風(fēng)格有自己的正則表達(dá)式語法和專用符號(hào),但功能非常有限。此功能不足不會(huì)成為障礙,因?yàn)?XSD 僅用于驗(yàn)證整個(gè)元素是否與模式匹配,而不是用于從大數(shù)據(jù)塊中提取匹配項(xiàng)。
XML 模式錨定整個(gè)正則表達(dá)式。因此,您不能添加正則表達(dá)式分隔符,也不需要使用錨點(diǎn)(即開頭的 ^ 和結(jié)尾的 $)。正則表達(dá)式必須匹配整個(gè)元素才能被視為有效元素。點(diǎn)從不匹配換行符,并且模式區(qū)分大小寫。 XML 正則表達(dá)式?jīng)]有像 \xFF 或 \uFFFF 這樣的任何標(biāo)記來匹配特殊字符,也沒有提供指定匹配模式的方法。
非貪婪行為沒有 XSD 語法。 XSD 也無法使用惰性量詞。由于模式錨定在主題字符串的開頭和結(jié)尾,并且只返回成功/失敗結(jié)果,這只是性能問題,導(dǎo)致貪婪和懶惰量詞之間存在差異。通過將貪婪量詞更改為惰性量詞或反之亦然,不可能使完全錨定的模式匹配或失敗。此外,沒有注冊(cè)或反向引用的子組沒有 XSD 語法。
不管其局限性如何,XML 模式正則表達(dá)式提供了兩個(gè)方便的特性。特殊的速記字符類 \i 和 \c 使得匹配 XML 名稱變得容易。沒有其他正則表達(dá)式支持這種可能性。
您不能直接在 FIND & REPLACE 語句中使用 XSD 語法,但您可以使用通過添加 REGEX 的方法 CREATE_XSD 創(chuàng)建的 RegEx 類的對(duì)象。
以下示例使用對(duì) PCRE 無效的 XSD 語法,并且找不到任何與 POSIX 匹配的語法。 它也適用于 XPath。
DATA(xml) = `<A><B>...<Y><Z>`.REPLACE ALL OCCURRENCES OFREGEX cl_abap_regex=>create_xsd( pattern = `\i\c*` )IN xml WITH `option:$0`.cl_demo_output=>display( xml ).結(jié)論
如前所述,正則表達(dá)式可以讓您解析字符串或復(fù)雜的替換操作。 它是一個(gè)強(qiáng)大的文本處理工具,可用于擴(kuò)展您的 ABAP 功能。 我希望我能讓你對(duì) RegEx 和 ABAP 中支持的語法,即 PCRE、XPath 和 XSD 有一個(gè)粗略的了解。
盡管 PCRE 功能更強(qiáng)大且可在大多數(shù)情況下使用,但最好使用 XPath 或 XSD 從 XML 文檔中選擇節(jié)點(diǎn)或計(jì)算值(如字符串、布爾值或數(shù)字),以更快更高效。 POSIX 語法現(xiàn)在已經(jīng)過時(shí),需要遷移到 ABAP 支持的任何其他正則表達(dá)式語法。 ABAP SQL 和 ABAP CDS 視圖還支持帶有上述內(nèi)置函數(shù)的 PCRE 語法。 更詳細(xì)的信息也可以在 ABAP 關(guān)鍵字文檔中找到。
總結(jié)
以上是生活随笔為你收集整理的现代 ABAP 编程语言中的正则表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flash如何结合Photoshop制作
- 下一篇: Express engine 学习笔记