grep là công cụ thiết yếu của sysadmin, tác dụng cơ bản là tìm một mẫu string trong 1 file text.
Cái tên grep bắt nguồn từ câu lệnh g/re/p của chương trình ed
> Its name comes from the ed command g/re/p (globally search for a regular expression and print matching lines)
Biết thêm một chút regex sẽ tăng thêm sức mạnh. Ví dụ in ra shell của các user trên máy:
$ grep -o '/bin/.*sh' /etc/passwd
/bin/bash
/bin/sh
Photo by Percy Pham on Unsplash |
Một "pattern" phổ biến là tìm số, nếu đã từng lập trình dùng regex, thì \d không còn lạ gì để tìm số - code Python ngay trên CLI:
$ echo '123ab45' | python3 -c '
> import re, sys
> print(re.findall("\d+", sys.stdin.read()))'
['123', '45']
Nhưng thật bất ngờ, grep trên Ubuntu 18.04 không hỗ trợ pattern này:
$ echo '123ab45' | grep -o '\d+'
# không in ra gì
Và nếu như bạn "có vẻ" là dân chuyên, "dùng egrep đi", thì kết quả cũng vẫn vậy:
$ echo '123ab45' | grep -oE '\d+'
# nguyễn y vân - vẫn y nguyên
Có thể bạn đã biết, trên Linux thường có thêm 2 câu lệnh fgrep và egrep, nhưng thực ra chúng chỉ là grep -F và grep -E
$ cat `which fgrep`
#!/bin/sh
exec grep -F "$@"$ cat `which egrep`
#!/bin/sh
exec grep -E "$@"
Nếu thực sự muốn thấy kết quả, phải dùng Perl Regex -P:
$ echo '123ab45' | grep -oP '\d+'
123
45
grep không chỉ là một chương trình
grep là tên của 1 loại chương trình, nó có nhiều "bản" khác nhau và các bản sẽ có vài phần giống và nhiều phần khác nhau.
Gõ grep --version để xem mình đang dùng gì:
$ grep --version
grep (GNU grep) 3.1
Copyright (C) 2017 Free Software Foundation, Inc.
Đây là GNU grep, mặc định trên các hệ điều hành Linux based.
Tren OSX/MacOS hay trên BSD, sẽ sử dụng bản grep khác
obsd# uname -a; grep --version
OpenBSD obsd.hvnbsd.com 6.8 GENERIC#97 amd64
grep version 0.9
Ba loại Regex mà grep hỗ trợ
khi gõ grep 'pattern' files, grep sẽ dùng Basic Regular Expression (BRE)
$ grep '/bin/.*sh$' /etc/passwd
Khi gõ egrep hay grep -E 'pattern' files, grep sẽ dùng Extended Regular Expression (ERE). BRE và ERE trong GNU grep về tính năng nhìn chung là giống nhau. Điểm khác biệt duy nhất là trong BRE, các ký tự đặc biệt phải escape với backslash \, ví dụ: () -> \(\)
grep understands three different versions of regular
expression syntax: “basic” (BRE), “extended” (ERE) and
“perl” (PCRE). In GNU grep there is no difference in
available functionality between basic and extended
syntaxes. In other implementations, basic regular
expressions are less powerful.
Perl-compatible regular expressions give additional
functionality, and are documented in pcresyntax(3) and
pcrepattern(3), but work only if PCRE is available in the
system.
Perl regex vốn nổi tiếng là nhiều tính năng, có thể dùng với option -P nếu trên máy có cài lib PCRE:
$ ldd `which grep` | grep pcre
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f92565f4000)
\d là cái gì?
Theo man 1 grep, bachslash (\) theo sau nó là 1 ký tự, thường là cách viết tắt (shortcut) cho các pattern regex thường dùng nào đó.Xem
bảng đầy đủ tại https://en.wikipedia.org/wiki/Regular_expression#Character_classes
trong grep, chỉ có \b \B \< \> \w - KHÔNG CÓ \d
The Backslash Character and Special Expressions
The symbols \< and \> respectively match the empty string
at the beginning and end of a word. The symbol \b matches
the empty string at the edge of a word, and \B matches the
empty string provided it's not at the edge of a word. The
symbol \w is a synonym for [_[:alnum:]] and \W is a
synonym for [^_[:alnum:]].
\d trong các chương trình khác có nghĩa là sẽ match 1 chữ số, trên grep phải viết rõ character class ra [0-9]
$ echo '123ab45' | grep -o '[0-9]\+'
123
45
Hay ERE không cần escape meta character +:
$ echo '123ab45' | grep -oE '[0-9]+'
123
45
Các character class định nghĩa sẵn theo man 7 regex:
Within a bracket expression, the name of a character class enclosed in "[:" and ":]" stands for the list of all characters
belonging to that class. Standard character class names are:
alnum digit punct
alpha graph space
blank lower upper
cntrl print xdigit
Regex là một vấn đề phức tạp, biết một chút cũng được nhưng nhớ nắm rõ các phiên bản, và tránh lạm dụng:
Some people, when confronted with a problem, think
“I know, I'll use regular expressions.” Now they have two problems.
Tham khảo
https://docs.python.org/3/library/re.html
https://blog.codinghorror.com/regular-expressions-now-you-have-two-problems/
Hết.
HVN at "học python tại PyMi" https://pymi.vn and https://www.familug.org
No comments:
Post a Comment