iT邦幫忙

2021 iThome 鐵人賽

DAY 4
0
Software Development

系統與服務雜談系列 第 4

grep - 3 Regex搭配淺談

grep回顧
grep簡介
grep - 2 用更多Option

Regexp

grep 可以搭配Regexp

Regex其實有分Basic Regexp(BRE)、Extended Regexp(ERE)、PerlRegexp

我這裡只舉出分別或差異, 如果...後面我想到要特別分享Regex在講完整點

BRE ERE 描述
+ >=1次
? 可選用的匹配, i.e. 出現0或1次
| Or
\{n,m\} {n,m} 匹配前面文字n到m次
\(\) () BRE是Back Reference, EXE則是分組

在BRE裡面遇到特殊符號像上面的{},(), 或者搜尋字串內真的是.*這種的,都需要透過\做轉義

案例分享

# 準備假資料
cat > grepText.txt <<EOF
love loove live l0ve lOve l@ve
EOF

grep 'l[a-zA-Z0-9]*ve' grepText.txt 

https://ithelp.ithome.com.tw/upload/images/20210908/20104930ARH5mrIXTw.png
這裡我們想找到滿足l(中間是字母或數字)ve的, 搭配Regexp的話通常就是[a-zA-Z0-9]*
但Regex也提供特定字元\w用來比對所有字母或數字

grep 'l\w*ve' grepText.txt

https://ithelp.ithome.com.tw/upload/images/20210908/20104930NBQQU48iM8.png

也能去找到滿足l(中間是非字母或數字)ve的, 搭配Regexp的話通常就是[^a-zA-Z0-9]*
^就是不包含以下字串的意思
也能透過\W來取代, 跟上面的\w比較, 這裡是大寫的W

grep 'l[^a-zA-Z0-9]*ve' grepText.txt; \
grep 'l\W*ve' grepText.txt

https://ithelp.ithome.com.tw/upload/images/20210908/20104930IPn0pLJZ4B.png

還有一種是字串邊界(Word Boundary), 就是找出完整的單字, 但這找出來的單字, 不是某個字串內的字.
透過\<單字\>或是\b單字\b來找尋.

# 準備假資料
cat > grepText.txt <<EOF
love loove live l0ve lOve l@ve lovelove
EOF

grep '\<love\>' grepText.txt; \
> grep '\blove\b' grepText.txt 

https://ithelp.ithome.com.tw/upload/images/20210908/20104930QYZzf065iW.png

但如果我們把*想改成+至少一次
會不會成功呢?
會發現都找不到
https://ithelp.ithome.com.tw/upload/images/20210909/201049300ewGMWs2iA.png
不然就是要加上\跳脫符號

這是因為+是extended
grep 搭配 extended Regex, 則需要搭配option -E, 或者用grep家族中的egrep

grep  -E 'l[a-zA-Z0-9]+ve' grepText.txt; \ 
> egrep 'l[a-zA-Z0-9]+ve' grepText.txt 

https://ithelp.ithome.com.tw/upload/images/20210909/20104930OT11BzUofm.png

還有個比較少用的
grep -F和grep家族中的fgrep,
用來快速查找字串用, 但不支持Regexp.

本日小結

grep提供非常多種Regexp的支持, 下篇在繼續分享.
在非常多文件, 或者文件內容非常多的時候, grep會非常好用又快速查找.

Question

能否用grep, 只取得這段文字中的數字呢?
累計文章數 5840篇 參賽組數 1087組 團隊組數 052隊 完賽人數 敬請期待

Ans:

echo "累計文章數 5840篇 參賽組數 1087組 團隊組數 052隊 完賽人數 敬請期待" | grep -oE '[0-9]{1,5}'
> 5840
> 1087
> 052

# 搭配Perl Regexp中的positive lookbehind, 找數字前面是空格的
# perl regexp這些用法日後再分享
echo "累計文章數 5840篇 參賽組數 1087組 團隊組數 052隊 完賽人數 敬請期待" | grep -oP '(?<= )\d+' 
> 5840
> 1087
> 052

上一篇
grep - 2 用更多Option
下一篇
awk - 簡介 Linux 製表好工具
系列文
系統與服務雜談32

尚未有邦友留言

立即登入留言