--- title: regex tags: learning notes, regex, Python --- # re - Regular expression operations * src: (https://docs.python.org/3/library/re.html) * 這個re模組提供與Perl類似的模式比對 * 被比對的模式或字串可以是Unicode strings[(str)](https://docs.python.org/3/library/stdtypes.html#str)或是8-bits strings[(bytes)](https://docs.python.org/3/library/stdtypes.html#bytes),但兩者因為類型不同,不能同時共用 * "正規表示法"跟"python"的backslash - "\\" 的使用方法是有衝突的 * python用\來顯示效果,可是RE卻是用\來脫離效果 >> Regular expressions use the backslash character (' \\ ') to indicate special forms or to allow special characters to be used without invoking their special meaning. This **collides with** Python’s usage of the same character for the same purpose in string literals * 解決的方式是在模式字串加入"r"字元(raw),就可以取消python字串的轉義功能 * 很重要的一點,絕大多數的正規表達式均可以先編譯,來提升之後的匹配速度 ## Regular Expression Syntax * 在RE模組的函式讓你確認“給定的RE”和“特定字串”是否一樣 * 不同的RE可以被串連成新的、更複雜的RE >> This holds unless A or B contain low precedence operations; boundary conditions between A and B; or have numbered group references. * RE可以包含簡單和特殊的字符(character) * 像"|" 和 "(" 等是特殊字符,他可以代表一個普通字符,或是去影響RE的意義 ### Speical character_特殊字符 |Pattern|Match(default)|fine-tuning|Match(after)| |:-:|-|:-:|-| |.| 任何字元(除了newline)|re.S, re.DOTALL, (?s)|任何字元 |^| 字串開頭|re.M, re.MULTILINE, (?m)|(每行)字串開頭 |$| 結尾是newline的字串結尾<br>字串結尾|re.M, re.MULTILINE, (?m)|(每行)結尾是newline的字串結尾| |*|修飾符,0或多個,越多越好(greedy)| |+|修飾符,1或多個,越多越好(greedy)| |?|修飾符,0或1個,越多越好(greedy)| |*?, +?, ??|修飾符,越少越好<br>(non-greedy/minimal fashion)| |{m}|m個連續的| |{m, n}|m到n個連續的(greedy)<br>忽略m等同0、忽略n等同無上限| |{m, n}?|non-greedy的{m, n}| |\ |轉義特殊字符(*, +, ?...)<br>表示特殊字組(\d, \w, \s...)| |[]|可以單獨列出字符e.g. [amk]<br>可以用"-"列出字符範圍e.g. [0-9]<br>使特殊字符失去特殊意義<br>可以接受特殊字組,Unicode str與8 bit還是有差<br>^在[]開頭可以實現反向選擇,其他位置無意義| |a\|b|a或b,符合其一就不再進行匹配<br>可以被用在群組裡<br>non-greedy| |(...)|匹配括號內的任何pattern,從頭到尾代表群組<br>括號的內容可以被取回,以`\number`再被匹配| |(?...)| ?後的第一個字符決定了架構的意義和語法<br>不會形成群組,(?P<name>...)是例外<br>下列是有支援的例子⬇︎| |(?aiLmsux)|一個或多個字母<br>re.A(ascii-only matching), re.I(ignorecase), re.L(locale dependent), re.M(muti-line), re.S(dot matchs all), re.U(unicode matching), re.X(verbose)| |(?: ...)|匹配括號內的任何pattern,從頭到尾代表群組<br>括號後的內容不行被取回| |(?aiLmsux-imsx:...)|0個或多個字母的aiLmsux<br>(選用)使用“-”跟著一或多imsx| |(?P<name>...)|與正常的括弧類似<br>括號的內容可以透過name被取回<br>已命名群組可以在三個地方被參考:<br>☞自己的模式裡面<br>☞處理match object時<br>☞在re.sub()的*repl*字串參數中| |(?=name)|一個已命名群組的backreference,匹配之前模式的群組name| |(?=#...)|註解,會被忽略| |prev(?=next)|prev,如果後面跟著next(lookahead assertion) | | prev(?!next) | prev,如果後面沒有跟著next(negative lookahead assertion) | | (?<=prev)next | 如果next前是prev,匹配next(lookbehind assertion) | | (?<!prev)next | 如果next前是不是prev,匹配next(negative lookbehind assertion) | |(?(id/name)yes-pattern\|no-pattern)|| ### Special sequence | Pattern | Match | | :--------: | -------- | | \d | 一個數字,同[0-9] | | \D | 一個非數字,同[^0-9] | | \w | 一個英數字元,同[a-zA-Z0-9_] | | \W | 一個非英數字元,同[^a-zA-Z0-9_] | | \s | 一個空白字元,同[ /t/n/r/f/v] | | \S | 一個非空白字元,同[^ /t/n/r/f/v] | | \b | 一個單字範圍 | | \B | 一個非單字範圍 | |\Z|字串的結尾,不包含newline| ## Module Contents * 這個模組定義了多組函式、常數和例外,有些函式為了(compile RE)編譯表達式,簡化了方法以方便使用 - re.compile(pattern, flags=0) - **將RE的pattern編譯成RE物件,在程式中重複使用更具效率** >>> flags values can be any of the following variables, combined using bitwise OR (the | operator). [re.A, re.debug, re.X...] ``` prog = re.compile(pattern) result = prog.match(string) ``` is equivalent to ``` result = re.match(pattern, string) ``` - re.rearch(pattern, string, flags=0) - **掃描整個字串,找到'第一個'匹配模式的位置並回傳匹配物件,若無,回傳`None`** - re.match(pattern, string, flags=0) - **若字串'開頭'匹配模式,回傳匹配物件;若無,回傳`None`** - re.fullmatch(pattern, string, flags=0) - **若'整個'字串匹配模式,回傳匹配物件;若無,回傳`None`** - re.split(pattern, string, maxsplit=0, flags=0) - **按照模式拆分字串。若在模式內使用括號,那模式內容也會回傳至串列中。** - re.findall(pattern, string, flags=0) - **回傳所有非重疊(non-overlapping)的匹配的'字串的串列',若無,回傳空匹配** - re.finditer(pattern, string, flags=0) - **回傳所有非重疊(non-overlapping)的匹配的'匹配物件',若無,回傳空匹配** - re.sub(pattern, repl, string, count=0, flags=0) - **很像字串方法replace(),repl可以是字串或函式** - re.escape(pattern) - **轉義在模式裡的特殊字符,當你想匹配的字串裡有metacharacter就會很好用** ## Regular Expression Objects * 編譯過的RE物件支援下列的方法和屬性 - Pattern.search(string, pos, endpos) - **掃描整個字串,找到'第一個'匹配模式的位置並回傳匹配物件,若無,回傳`None`** ## Match Objects * match object是boolean: `True`,所以可以用if statement檢視是否匹配 ``` match = re.search(pattern, string) if match: process(match) ``` * 匹配物件支援下列的方法和屬性 - Match.expand(template) - ??? - Match.group([group1,...]) - 回傳一或多個匹配的子群組 - 如果是一個引數,回傳一個字串;如果是多個引數,以tuple形式回傳多個 - 如果群組數字是負的或是大於群組數量,Error - 如果RE用(?P<name>)語法,那引數需為字串形式 `m = re.match(r"(?P<first_name>) (?P<last_name>)", "HungYi Yu")` `m.group('first_name')` - 若重複匹配多次,取最後一次 - Match.\_\_getitem__(g) - 與m.group(g)相同,更容易寫 `m = re.match(r"(\w+) (\w+)", "HungYi Yu")` `m.group[0]` - Match.groups(default=None) - 以tuple形式回傳所有子群組 - Match.groupdict(default=None) - 以字典形式回傳所有子群組 - Match.start([group]) / Match.end([group]) - 回傳子字串開頭和結尾的索引