Regular expression

From LemonWiki共筆
Revision as of 11:29, 17 August 2019 by Planetoid (talk | contribs)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

透過正規表示法 (Regular Expression) 處理文字檔時,可以快速地搜尋或取代符合特定規則的字串。以每行為單位,進行字串處理[1]。 正規表示法 又稱正規表示式、正規表達式、正則表達式、正規表示法、正規運算式、規則運算式、常規表示法[2]

Raise_hand.png 有問題嗎?可以利用提供解說的 線上工具,嘗試自己除錯。 也可以到看板 RegExp 文章列表 - 批踢踢實業坊或其他問答服務詢問。

快速查表

說明: (1) sample 藍色網底處代表符合規則的文字、(2) 同一文字規則可以有多種表示法

文字規則 sample 對立的文字規則 sample
任意一個文字(包含空白,但不包含換行符號)
.
What Does the Fox Say? 12 狐狸怎叫 34
任意文字(包含空白),出現1次或0次
.? = .{0,1}
What Does the Fox Say? 12 狐狸怎叫 34
任意次的多個文字(包含空白)
.* = .{0,}
What Does the Fox Say? 12 狐狸怎叫 34
任意次的文字(包含空白),至少出現1次
.+ = .{1,}
What Does the Fox Say? 12 狐狸怎叫 34
任意次的空白或換行符號 (至少出現1次的空白或換行符號)
\s+
What Does the Fox Say? 12 狐狸怎叫 34 任意多個文字(不包含空白或換行符號)
[^\s]+ = [^\s]{1,} = [\S]+ = [^ ]+
What Does the Fox Say? 12 狐狸怎叫 34
任意次的 ASCII character(包含英文、數字和空白) demo[3]
[\x00-\x80]+[[:ascii:]]+[4]
What Does the Fox Say? 12 狐狸怎叫 34 非 ASCII,即中文出現任意次
[^\x00-\x80]+
What Does the Fox Say? 12 狐狸怎叫 34
任意次的大小寫英文、數字和底線符號( _ )文字(不包含空白)
[\w]+ = [a-zA-Z0-9_]+
What Does the Fox Say? 12 狐狸怎叫 34 任意次的不是英文、數字和底線符號( _ )的文字
\W+ = [^a-zA-Z0-9_]+
demo
任意次的數字(不包含空白)
[\d]+ = [0-9]+
What Does the Fox Say? 12 狐狸怎叫 34 不包含數字的任意次文字(包含空白
[^\d]+ = [^0-9]+ = \D+
What Does the Fox Say? 12 狐狸怎叫 34
任意次的中文字
[\p{Han}]+ (demo 詳細說明)
What Does the Fox Say? 12 狐狸怎叫 34 不包含中文字的任意次文字
[^\p{Han}]+ (demo)
以「狐狸」開頭的行
^狐狸.*$[5]

狐狸怎叫 34 What Does the Fox Say?
柴犬怎叫 What Does the shiba inu say?

不以「狐狸」開頭的行
^(?!狐狸).*$[6]

狐狸怎叫 34 What Does the Fox Say?
柴犬怎叫 What Does the shiba inu say?

以「怎叫」結尾的行
^.*怎叫$

What Does the Fox Say? 12 狐狸怎叫 34
What Does the shiba inu say? 柴犬怎叫

不以「怎叫」結尾的行
.*(?<!怎叫)$[7]

What Does the Fox Say? 12 狐狸怎叫 34
What Does the shiba inu say? 柴犬怎叫

包含「狐狸」的行
^.*狐狸.*$

What Does the Fox Say? 12 狐狸怎叫 34
What Does the shiba inu say? 柴犬怎叫

不包含「狐狸」的行
^((?!狐狸).)*$

What Does the Fox Say? 12 狐狸怎叫 34
What Does the shiba inu say? 柴犬怎叫

布林邏輯 AND: 包含「狐狸」和「叫」的行 (demo)[8]
(?=.*狐狸)(?=.*叫).*

What Does the Fox Say? 12 狐狸怎叫 34
What Does the Fox Say? 12 不叫狐狸 34
What Does the shiba inu say? 柴犬怎叫

布林邏輯 OR: 包含「狐狸」或「叫」的行 (demo)
.*(狐狸|叫).*

What Does the Fox Say? 12 狐狸怎叫 34
What Does the shiba inu say? 柴犬怎叫

What Does the shiba inu say? 柴犬怎了

布林邏輯: 不包含「狐狸」也不包含「柴犬」的行
^((?!狐狸|柴犬).)*$
What Does the Fox Say? 12 狐狸怎叫 34

What Does the shiba inu say? 柴犬怎叫

What Does the Husky say? 哈士奇怎叫
布林邏輯 NOT: 不包含「狐狸」,但包含「柴犬」的行 (demo)[9]
^((?!狐狸).)*(柴犬).*$ = ^(柴犬).*((?!狐狸).)*$ = (柴犬).*((?!狐狸).)*

What Does the Fox Say? 12 狐狸怎叫 34
What Does the shiba inu say? 柴犬怎叫

Regular expression online tools

examples

cases

取代換行符號為逗號

將Email清單,轉成Email軟體可以使用的寄信名單

[email protected]
[email protected]
[email protected]

改成
[email protected],[email protected],[email protected]

方案1: Sublime Text, EmEditor

語法適用 Sublime Text, EmEditor軟體 (以下為 EmEditor 的操作說明)

  1. Menu: Search -> Replace
  2. click "Use Regular Expression"
    1. Find: \n ( 換行符號Win Os windows.png 作業系統的換行符號是 \r\nMac icon_os_mac.png 作業系統的換行符號是 \n,取兩者共有的符號。如果使用 Linux Os linux.png 作業系統的換行符號是 \r。 )
    2. Replace with: ,
  3. click "Replace all"


將每行的文字,移除換行,並且都加上逗號分隔
// before
Elmo
Emie
Granny Bird

// after
Elmo, Emie, Granny Bird

方法: 使用 Sublime TextEmEditor

  • Find what: \n
  • Replace with: , 此例是將每行的文字,都加上逗號+空格分隔 (如果要用別的符號分隔,例如頓號分隔,則是 Replace with: )


將逗號分隔的文字,還原成逐行顯示,並且移除分隔符號 (,)
// before
Elmo, Emie, Granny Bird

// after
Elmo
Emie
Granny Bird

方法: 使用 Sublime TextEmEditorIcon_exclaim.gif 輸出結果的每行前面可能會有空白

  • Find what: ([^,]+),
  • Replace with: \1\n
 

方案2: Notepad++

使用Notepad++軟體

  1. 選單: 尋找 -> 取代
  2. 搜尋模式: 勾選「增強模式」 (不是勾選「用類型表式」)
    1. 尋找目標: \n (換行符號)
    2. 取代成: ,
  3. 勾選全部取代

相關資料: How To Replace Line Ends, thus changing the line layout last visited: 2010-01-27

方案3: Microsoft Word

使用Microsoft Word 2002軟體

  1. 選單: 編輯 -> 取代
  2. 勾選增強模式
    1. 尋找目標: ^p (段落標記)
    2. 取代為: ,
  3. 勾選全部取代

方案4: Sed command for linux

sed 's/要被取代的字串/新的字串/g' old.filename > new.filename[10]

(1)要被取代的字串: :a;N;$!ba;s/\n (2)新的字串: ;

sed ':a;N;$!ba;s/\n/; /g' old.filename > new.filename [11]

方案5: 使用支援十六進位編輯 (HEX) 的編輯軟體

使用支援十六進位編輯 (HEX) 的編輯軟體,例如: ‎iHex - Hex Editor for Mac icon_os_mac.png

  1. 選單 Edit -> Find
  2. Find: 0A 換行符號
  3. Replace: 2c 20 其中 2c 是逗號, 20 是空白
  4. 儲存檔案

相關資料

Find IP address (IPv4)

適用 Notepad++ 軟體 v.5.9.5

  1. 選單: 尋找 -> 取代
  2. 搜尋模式: 勾選「用類型表式」
    1. 尋找目標: \d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?

note: not support {n} syntax

適用 Sublime Text v. 3.2.21

  1. Find: (?:\d{1,3}\.){3}\d{1,3}

參考資料:

移除記事本純文字檔的黑色方塊(UNIX系統的換行符號 LF )

使用notepad++軟體

  1. 選單: 尋找 -> 取代
  2. 搜尋模式: 勾選「增強模式」
    1. 尋找目標: \n\n (註: 2個LF )
    2. 取代成: \r\n (註: CR與LF )

用記事本打開純文字檔時,就不會看到黑色方塊


將每項元素,加上引號框起來

將陣列的每項元素,都加上引號框起來

Elmo, Emie, Granny Bird, Herry Monster, 喀喀獸
修改成
'Elmo', 'Emie', 'Granny Bird', 'Herry Monster', '喀喀獸'

方法1: 使用 PHP Icon_exclaim.gif 如果元素包含換行符號,不能用下面方法處理。

$users = array('Elmo', 'Emie', 'Granny Bird', 'Herry Monster', '喀喀獸');
//「單引號」相隔每個元素
$result = implode(",", preg_replace('/^(.*?)$/', "'$1'", $users));

//「雙引號」相隔每個元素
$result = implode(",", preg_replace('/^(.*?)$/', "\"$1\"", $users));
echo $result;

Thanks, Joshua! More on PHP - Wrap Implode Array Elements in Quotes » Me Like Dev

方法2: 使用 Sublime TextEmEditor

  • Find: ([^\s|,]+)
  • 分隔符號
    • 「單引號」相隔每個元素 Replace with: '\1'
    • 「雙引號」相隔每個元素 Replace with: "\1"

方法3: 使用 Notepad++。啟用搜尋模式的「用類型表式」

  • Find: ([^\s|,]+)
  • 分隔符號
    • 「單引號」相隔每個元素 Replace with: '$1'
    • 「雙引號」相隔每個元素 Replace with: "$1"


將每行的文字,都加上引號框起來,並且移除換行

// before
Elmo
Emie
Granny Bird

// after
'Elmo', 'Emie', 'Granny Bird'

方法1: 使用 Sublime TextEmEditor。該方法有處理每行的前面或後面可能有一格或多格空白

  • Find what: (\S+)(\s?)+$\n
  • Replace with: '\1',
    (如果要使用雙引號框起來,則是 Replace with: "\1", )

方法2: 使用 Sublime TextEmEditor Icon_exclaim.gif 該方法沒有處理每行的後面可能有一格或多格空白

  • Find what: (.*)$\n(\S+)$\n(\S+)\n
  • Replace with: '\1',


將引號框起來的文字,還原成逐行顯示,並且移除分隔符號 (,)

// before
'Elmo', 'Emie', 'Granny Bird'

// after
Elmo
Emie
Granny Bird

方法: 使用 Sublime TextEmEditor。該方法有處理每行的前面或後面可能有一格或多格空白

  • Find what: '(([^,|^'])+)',?\s?
  • Replace with: \1\n
 


將試算表欄位值前後,加上雙引號框起來

尋找中文、非英文的文字

適用: Google Drive 試算表的 Regular expression 相關函數,例如: REGEXMATCHREGEXEXTRACTRegExReplace 函數、Notepad++的搜尋

[^\x00-\x80]+

適用: LibreOffice REGEX function[12]、Total commander 的 Multi-Rename tool[13][14]

[^\u0000-\u0080]+

尋找欄位值包含中文字,適用: MySQL[15]

SELECT `column_name`
FROM `table_name`
WHERE HEX(`column_name`) REGEXP '^(..)*(E[4-9])';

尋找欄位值包含中文字,中文字包含繁體中文與簡體中文,不包含特殊符號,例如 Emoji:。 PHP:

// approach 1
if (preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $string)) {
	echo "全部文字都是中文字" . PHP_EOL;
}else{
	echo "部分文字不是中文字" . PHP_EOL;
}

// approach 2
if (preg_match('/^[\p{Han}]+$/u', $string)) {
	echo "全部文字都是中文字" . PHP_EOL;
}else{
	echo "部分文字不是中文字" . PHP_EOL;
}

技術問題除錯:

  • 錯誤訊息:
    preg_match(): Compilation failed: character value in \x{} or \o{} is too large at offset 8

解決方式: preg_match() 需要加上 u 變數[16]

參考資料:

將每行文字的行頭加上逗號符號

使用notepad++軟體

  1. 選單: 尋找 -> 取代
  2. 搜尋模式: 勾選「用類型表示」
    1. 尋找目標: (.*) 或者是 ^(.*)$
    2. 取代成: ,\1 或者是 ,$1

參考資料: Notepad++ RegEx Search/Replace: How to append and prepend a character at start and end of each file line? - Stack Overflow

知道前面跟後面的文字,但是中間文字忘記了

使用notepad++軟體

  1. 選單: 尋找 -> 取代
  2. 搜尋模式: 勾選「用類型表示」
    1. 尋找目標: a(.*)le 就可以找到(1)apple (2)apps lesson ... 等a開頭、le結尾的文字,中間可夾雜空白。 Icon_exclaim.gif 中文字串搜尋,建議將文件的編碼改成 UTF-8 編碼


移除空白行

# (原) 每行可能間隔一行空白或多行空白
尼歐
崔妮蒂

莫斐斯


史密斯
祭師

# (後) 改成每行逐行緊接著
尼歐
崔妮蒂
莫斐斯
史密斯
祭師

移除一行空白或多行空白( 行內可能包含一個或多個空白字元 SPACE 、定位鍵TAB)

  • 使用工具: 適用 Sublime Text 與 EmEditor 軟體,需勾選「使用規則運算式」。Icon_exclaim.gif 以下語法不適用於 Notepad++ 軟體[17]
    • 尋找: ^[\s\t]*$\n --> 取代為: 空 (不需要輸入任何字)
  • 使用工具: Notepad++
    • Notepad++ 軟體選單: 編輯 -> 行列 -> 移除空行(含空白字元 SPACE )[18]
  • 詳細說明,請見 Regular replace blank lines

尋找非空白的文字

將特定符號相隔的文字,改成逐行顯示

例子:

# (原) 頓號(、)符號相隔的文字
尼歐、莫斐斯、崔妮蒂、史密斯、祭師

# (後) 改成逐行顯示
尼歐
莫斐斯
崔妮蒂
史密斯
祭師

使用 Sublime TextEmEditor

  • Find: ([^、]+)([、]{1})
  • Replace with: \1\n

語法說明

  • [^、] : 符合任意字,但不是頓號(、)的文字
  • [^、]+ : 一次以上不是頓號(、)的文字
  • ([^、]+) : 符合「一次以上不是頓號(、)的文字」規則的文字
  • [、]: 出現頓號(、)任意次的文字
  • [、]{1} : 出現頓號(、)一次的文字
  • ([、]{1}) : 符合「出現頓號(、)一次的文字」規則的文字


將每行文字的結尾處,加入空一格 (半形空白)

法1: 適用軟體: Sublime Text, EmEditor

  1. Menu: Search -> Replace
  2. click "Use Regular Expression"
    1. Find: \n
    2. Replace with: _\n(符號 \n 前面的 _ 自行替換成半形空白)
  3. click "Replace all"


法2: 適用軟體: Sublime Text, EmEditor

  1. Menu: Search -> Replace
  2. click "Use Regular Expression"
    1. Find: $
    2. Replace with: _$(符號 $ 前面的 _ 自行替換成半形空白)
  3. click "Replace all"


Icon_exclaim.gif 需要檢查最後一行是否是空白行,如果不是空白行,不會套用到該取代規則

將每行文字內夾雜的空白,取代成 Tab 符號

將原本空白間隔的欄位值,取代成 Tab鍵間隔的欄位值。輸出結果可以方便貼到 MS Excel 或 Google spreadsheet

# \t 代表是 Tab 鍵,又稱定位鍵
# before
aaa bbb    ccc

# after
aaa\tbbb\tccc

說明: \S 代表非空白字元, \r\n 代表 換行符號。[^\S\r\n] 則代表不是非空白字元、也不是換行符號。換句話說尋找空白,但不包含換行符號。

使用 Sublime Text 軟體 (參考資料[19] [20])

  1. Menu: Search -> Replace
  2. click "Use Regular Expression"
    1. Find: ([^\S\n]+)([^\S\r\n]+)\s\s+_{1,} ( 自行替換 _ 成半形空白) Icon_exclaim.gif 因為 \s 包含了空白與換行字元,所以不能直接使用 \s+ 當做搜尋條件
    2. Replace with: \t
  3. click "Replace all"

移除每行文字前後面可能多個的空白

移除每行文字最前面可能多個的空白

  • 尋找: ^\s+ --> 取代為: 空白 (適用軟體: Sublime Text、EmEditor,需啟用 "Use Regular Expression" )
# before
aaa 
 bbb
    ccc

# after
aaa 
bbb
ccc


移除每行文字最後面可能多個的空白

  • 尋找: \s+$ --> 取代為: 空白 (適用軟體: Sublime Text、EmEditor,需啟用 "Use Regular Expression" )


移除每行文字前面或後面可能多個的空白

  • 尋找: (^\s+|\s+$) --> 取代為: 空白 (適用軟體: Sublime Text、EmEditor,需啟用 "Use Regular Expression" )

尋找包含不是數字,是文字的行

預期每行資料都是數字,尋找包含不是數字,是文字的行

[^\d|\n]

尋找 Hashtag

Extract all hashtags from text

尋找文章內容中的網址

Regular extract url from text

尋找數字

請參考 Data cleaning#Numeric

尋找文章內容中的長數字

Extract large number from text

Search unmatched string

find un-commented console.log:

original format: some lines contains un-commented Javascript debug information

   console.log("un-commented debug information");

  //console.log("commented debug information");

Search pattern: find not started with the / symbol before the string "console.log"

   [^/](console\.log)

Regular expression batch tools

multiple regular expression operations on the same file

one regular expression operations on multiple files

syntax

  • 換行符號: \r\n (適用: Notepad++選項: 增強模式 & 用類型表式)
  • tab鍵的固定空白分隔: \t (適用: Notepad++選項: 增強模式)
  • 數字: \d (適用: Notepad++選項: 用類型表式。Icon_exclaim.gif 不適用: Notepad++選項: 增強模式)
  • \S 非空白的文字: 不會含括半形空白與全行空白

Troubleshooting of regular expression

Tips

  • Small data test: (1) Prepare the small file data to verify the syntax (2) Using the online tools
  • Highlight or output the matched text e.g. --color[21] for grep command or output the matches by PHP preg_match() function.
  • Simplify the syntax
  • Because the compatibility issue, you may try to use the alternative syntax e.g. \d to [0-9]+.

Related articles

further reading

unicode

references

  1. 鳥哥的 Linux 私房菜 -- 正規表示法 (regular expression, RE) 與文件格式化處理
  2. 正規表示式 - 維基百科,自由的百科全書
  3. Ascii Table - ASCII character codes and html, octal, hex and decimal chart conversion
  4. php - Regex for Any English ASCII Character Including Special Characters - Stack Overflow
  5. Regex Examples: Matching Whole Lines of Text That Satisfy Certain Requirements
  6. regex - Regular expression to match text that *doesn't* contain a word? - Stack Overflow
  7. Regex not ending with - Stack Overflow
  8. regex - Regular Expressions: Is there an AND operator? - Stack Overflow
  9. regex - Regular expression for a string containing one word but not another - Stack Overflow
  10. 鳥哥的 Linux 私房菜 -- 正規表示法 (regular expression, RE) 與文件格式化處理
  11. 參考 unix - sed: How can I replace a newline?
  12. List of Regular Expressions
  13. 取代非英文的文字,但是不包含 . 符號: [^\u0000-\u0080|.]+
  14. javascript - Regular expression to match non-english characters? - Stack Overflow
  15. How to detect rows with chinese characters in MySQL? - Stack Overflow
  16. php - preg_match(): Compilation failed: character value in \x{} or \o{} is too large at offset 27 on line number 25 - Stack Overflow
  17. Regex: delete multiple blank lines
  18. regex - Removing empty lines in Notepad++ - Stack Overflow
  19. Quickly replace multiple space characters with a tab character - TechRepublic
  20. regex - Match whitespace but not newlines (Perl) - Stack Overflow
  21. Grep -color command Examples - nixCraft

替代方案

  • 將資料以 Tab來隔開,貼到Google Drive的Spreadsheet或MS Excel,會自動儲存到不同欄位。所以將需要處理的原始資料中,需要擷取的資料的前後,使用Tab來隔開,複製後貼到於Google Drive的Spreadsheet或MS Excel,就會自動儲存到不同欄位,方便做進一步處理。

Copy multiple rows & paste

  • Copy to dreamweaver from MS Excel 2002: ok
  • Copy to dreamweaver from Google Docs: not ok Icon_exclaim.gif
  • Copy to MS Excel 2002 from Google Docs: ok


Troubleshooting of ...

Template