Grep Expression
Bài đăng này đã không được cập nhật trong 4 năm
Mình bắt đầu grep như thế nào?
Ngày đầu chập chững bắt đầu biết cách grep log là gì thì rất háo hức muốn được lên môi trường production or staging thử vài đường cơ bản cho nó mượt. Cơ mà đời không như mơ, local thì chỉ toàn touch file_test xong rồi grep 'kem danh rang ps' file_test -> không có kết quả => dễ vãi =)))) .
Đến lúc lên môi trường production grep 'tay trang moi vet ban' *.log
1s
2s

5s

...
10s

À mà trong lúc chờ đợi tiện thể ta tìm hiểu grep là gì cái nhỉ!
Ai cũng biết grep được sử dụng để tìm kiếm một chuỗi kí tự truyền vào trong 1 file or nhiều file. Xúc tích thì nó là như thế! cơ mà không biết có ai tò mò nghĩa của từ grep là gì không, ai cũng có thể đoán ra đó là tìm kiếm nhưng ...
30s
!!!Bùm!!!





















































thôi nghỉ m* đi! méo có grep gờ riếc gì ở đây hết.
Nói thế chứ pha vừa rồi là do mình grep ngu thôi chứ dự án mình khi muốn thao tác trên môi trường prod thì sẽ phải pass 1 bài test nhỏ
- mình mới nghĩ ra đấy haha :3
HW: Grep toàn bộ biến ENV của dự án ra một file rồi compare với file .env hiện tại. (Ruby project)
file .env dạng
API_LINK="https://google.com"
SLACK_HOOK_URL="https://ksjkd.com"
...
một file trong hệ thống có sử dụng ENV ví dụ như
if ENV["VERSION_OS"] > 1
puts "Need to be updated."
end
Bài toán
Mặc dù nói là bài test nhưng ta cũng phải hiểu xem tại sao lại có bài toán trên.(hình như làm cái gì cũng phải hiểu vấn đề thì mới giải quyết được nhanh và tốt nhất :v)
Dự án mình có khá nhiều server chạy app - đâu đó khoảng chục con đi
, check file .env giữa các con server thì đang có sự sai khác. Tại sao lại khác thì lại là câu chuyện của các Fn đời trước của dự án, tại sao khi thêm ENV lại không thêm ở tất cả các con server - Vì ngại phải add từng con một chăng? Hoặc cũng có thể do ENV không được dùng nữa nhưng các con server cũng chưa xóa đi => Dẫn đến việc sai khác ENV variables giữa các môi trường.
Vậy nên mục đích cuối cùng là list up những ENV nào đang được sử dụng trong hệ thống và compare ENV giữa các server để có giải pháp xử lý đồng bộ ENV giữa tất cả con server vì biến này dùng được ở toàn hệ thống.
Hiểu được tại sao lại có vấn đề rồi thì bắt đầu grep thôi
))
chắc sẽ có nhiều cách khác nhưng trong bài biết này thì ý tưởng của mình là grep
1. First step: grep trong 1 file
Ví dụ file test.text chứa ENV:
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ cat test.text
vand
asdasd
if ENV["API_LINK"] == "https://google.com"
puts "van"
end
webhook_url = ENV["WEBHOOK_URL"]
grep ENV trong file test.text
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ grep ENV test.text
if ENV["API_LINK"] == "https://google.com"
webhook_url = ENV["WEBHOOK_URL"]
Ơ, nó in ra cả line chứa kí tự ENV mất rồi, cos option nào chỉ in ra text match vs input không nhỉ?
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ grep -o ENV test.text
ENV
ENV
Có rôi nè -o or only-matching sẽ in ra kí tự bạn grep. Cơ mà ta grep thế này để làm gì nhỉ?. Yêu cầu là phải grep ra tất cả các biến ENV có nhưng tên khác nhau cơ mà, ta có thông tin là
- Format các biến
ENVđều giống nhau ví dụ:ENV["WEBHOOK_URL"] - Tất cả đều viết hoa và ngăn cách nhau bởi dấu
_
Vậy thì việc tiếp theo là regex cái chuỗi này ENV["WEBHOOK_URL"]
- > Ta gọi đó là Grep Expression
2. Second step: grep regex
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ grep -o 'ENV\[' test.text
ENV[
ENV[
Output nếu chưa các kí tự đặc biệt như [, *, ... thì thêm \ => cũng khá giống với regex ở các ngôn ngữ lập trình nhỉ :3
Tiếp theo ta thêm
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ grep -o 'ENV\[".*[A-Z0-9]' test.text
ENV["API_LINK
ENV["WEBHOOK_URL
ENV["ENV_NUMBER
giải thích
. kí tự bất kì
* số lần lặp bất kì
=> ghép lại ta sẽ lấy được tất cả kí tự sau 'ENV[" như sau:
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ grep -o 'ENV\[".*' test.text
ENV["API_LINK"] == "https://google.com"
ENV["WEBHOOK_URL"]
ENV["ENV_NUMBER1"]
Cho nên ta phải định nghĩa format mà thằng * sẽ lấy kí tự bằng cách t hêm [A-Z0-9]
=> Zậy là xong - đây cũng chỉ là cách do mình nghĩ ra thôi nếu có suggest thêm xin hãy để lại comment bên dưới 
SUN-ASTERISK\nguyen.dang.van@b121765-lt1:~$ grep -o 'ENV\[".*[A-Z0-9]"\]' test.text
ENV["API_LINK"]
ENV["WEBHOOK_URL"]
=> Về cơ bản thì nó cũng không khác cách regex của các ngôn ngữ khác
Step 3: grep cả project
Ai lại vào từng folder grep như thế này nhỉ :3
grep -o 'ENV\[".*[A-Z0-9]"\]' *
Quê quá!!! -.-
Đầu tiên
grep -r -o 'ENV\[".*[A-Z0-9]."\]' *
lib/tasks/db.rake:ENV["MODEL"]
lib/tasks/migrate.rake:ENV["MODELS"]
Với option -r ta sẽ grep tất cả các file trong tất cả các sub-directories.
Vì nó show ra cả tên file nữa nên ta sẽ sử dụng grep lồng như sau
grep -r ENV | grep -o 'ENV\[".*[A-Z0-9]"\]'
ENV["API_LINK"]
ENV["WEBHOOK_URL"]
ENV["WEBHOOK_URL"]
Để tránh trường hợp bị trùng ENV ta thêm option sort --unique
grep -r ENV | grep -o 'ENV\[".*[A-Z0-9]"\]' | sort --unique
Step 4: gán
Suýt quên cần file gán vào file lưu lại rồi compare nữa chứ
grep -r ENV | grep -o 'ENV\[".*[A-Z0-9]"\]' | sort --unique > env_to_compare.text
!!!Bùm!!!
Quay lại đầu bài grep là gì trước khi compare nhá :v
Google translate thì bảo là
nắm chặtFacebook thì chả bảo gì
Wiki thì nói nó là viết tắt của cụm
g/re/p(search for a regular expression and print matching lines)
~~
Thôi nghỉ đã bài sau compare tiếp nhé!!!

Hy vọng bài viết giúp ích cho các bạn!
Tham khảo:
Definition: https://en.wikipedia.org/wiki/Grep
Grep regular ex: https://www.digitalocean.com/community/tutorials/using-grep-regular-expressions-to-search-for-text-patterns-in-linux
Grep all files: https://www.cyberciti.biz/faq/grep-subdirectory-for-files-on-linux-bsd-osx-unix-oses/
All rights reserved

