0

Grep Expression

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ặt

Facebook 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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí