15+ mẹo và thủ thuật Bash giúp bạn làm chủ dòng lệnh Linux (Phần 4)

15+ mẹo và thủ thuật Bash giúp bạn làm chủ dòng lệnh Linux (Phần 4)

Trong phần tiếp theo của chuỗi bài viết chuyên sâu về dòng lệnh Bash, chúng ta sẽ cùng khám phá kỹ thuật grep nâng cao để trích xuất chính xác nội dung cần thiết, đi kèm với hướng dẫn cách sử dụng pwd nhằm xác định đúng thư mục nơi một Bash script được khởi chạy.

DataOnline sẽ hướng dẫn bạn cách học :

  • Các mẹo, thủ thuật và phương pháp hiệu quả khi dùng dòng lệnh Bash
  • Cách tương tác nâng cao với Bash shell
  • Cách cải thiện toàn diện kỹ năng Bash và trở thành người dùng Bash chuyên nghiệp hơn

Yêu cầu phần mềm và quy ước sử dụng

Danh mục Yêu cầu, quy ước hoặc phiên bản phần mềm được sử dụng
Hệ thống Linux – không phụ thuộc vào bản phân phối
Phần mềm Bash command line, hệ điều hành nền tảng Linux
Khác Bất kỳ tiện ích nào không được tích hợp sẵn trong Bash có thể cài đặt bằng sudo apt-get install utility-name (hoặc yum install trên hệ RedHat)

Các quy ước

  • # – yêu cầu lệnh được thực thi với quyền root (trực tiếp hoặc dùng sudo)
  • $ – lệnh được chạy với quyền người dùng thường

Ví dụ 1: Đường dẫn thư mục làm việc – Có đúng như bạn nghĩ?

Chúng ta thường sử dụng lệnh pwd trong dòng lệnh để biết thư mục hiện tại:

$ pwd
/home/roel/workspace

Nhưng nếu ta muốn lấy thư mục mà một script được khởi chạy từ đó, liệu cách sử dụng biến trong script có cho ra kết quả tương tự?

$ cat test_pwd.sh 
#!/bin/bash
MY_PATH1="${PWD}"
echo "${MY_PATH1}"
MY_PATH2="$(pwd)"
echo "${MY_PATH2}"

Trong ví dụ này, ta dùng hai cách để lấy đường dẫn:

  • MY_PATH1 sử dụng biến $PWD – biến môi trường tự động có sẵn
  • MY_PATH2 dùng kết quả thực thi lệnh pwd trong subshell $(...)

Kết quả khi chạy script:

$ ./test_pwd.sh 
/home/roel/workspace
/home/roel/workspace

Mọi thứ có vẻ ổn. Nhưng khi chúng ta chuyển sang một thư mục khác và gọi script bằng đường dẫn tương đối hoặc đầy đủ, thì pwd hoặc $PWD bên trong script sẽ trả về thư mục chúng ta đang đứng lúc gọi, chứ không phải nơi script thật sự nằm.

$ mkdir test
$ cd test
$ ../test_pwd.sh
/home/roel/workspace/test
/home/roel/workspace/test

Bạn thấy đấy, pwd hay $PWD sẽ luôn trả về đường dẫn hiện tại, chứ không phải nơi script đang cư trú.

Vấn đề này khá phổ biến trong các Bash script phức tạp có nhiều script con hoặc các file cấu hình đi kèm. Vậy làm thế nào để lấy chính xác đường dẫn nơi script được khởi chạy từ đó?

Hướng tiếp cận 1 – Dùng dirname "$0"

$ cat test2.sh 
#!/bin/bash
echo "\$0"
dirname "\$0"

$0 là một biến đặc biệt, chứa tên script khi được khởi chạy. dirname sẽ lấy ra phần thư mục từ tên file được truyền vào.

Thử chạy:

$ ./test2.sh 
./test2.sh
.
$ cd test
$ ../test2.sh 
../test2.sh
..

Cách này tốt hơn, nhưng vẫn chưa phải là đường dẫn tuyệt đối.

Hướng tiếp cận 2 – Dùng cd "$(dirname "$0")" && pwd

Giải pháp lý tưởng: bao dirname bên trong cd, sau đó dùng pwd để lấy đường dẫn tuyệt đối:

$ cat make_it_work.sh 
#!/bin/bash
MY_PATH="$(cd "$(dirname "\$0")" && pwd)"
echo "${MY_PATH}"

Chạy thử:

$ ./make_it_work.sh 
/home/roel/workspace

Giờ ta thử chạy từ thư mục con:

$ cd test && pwd
/home/roel/workspace/test
$ ../make_it_work.sh 
/home/roel/workspace
$ /home/roel/workspace/make_it_work.sh 
/home/roel/workspace

Hoàn hảo!

Trong cả hai trường hợp – dù bạn gọi script bằng cách tương đối (../) hay bằng đường dẫn đầy đủ (/home/roel/workspace/), thì kết quả thu được vẫn là thư mục nơi script được khởi chạy (/home/roel/workspace/), chứ không phải thư mục làm việc hiện tại, hay giá trị trả về từ pwd (/home/roel/workspace/test).

Tóm lại, bạn có thể sử dụng đoạn lệnh một dòng MY_PATH="$(cd "$(dirname "$0")" && pwd)" trong script để lấy chính xác đường dẫn tuyệt đối của thư mục chứa script. Sau đó, việc sử dụng đường dẫn tương đối dựa trên biến này sẽ rất dễ dàng và hiệu quả. Ví dụ, bạn có thể gọi đến ${MY_PATH}/include/mysubscript.sh hoặc thậm chí ${MY_PATH}/../one_dir_up_file.txt một cách an toàn.

Ví dụ 2: Grep chính xác thứ bạn cần

Chắc hẳn bạn đã dùng grep – một công cụ cực kỳ mạnh mẽ để tìm kiếm chuỗi văn bản trong file.

$ cat test
line 1 my line
line 2 your lines
line 3 our line
$ grep 'line 2' test
line 2 your lines

Chúng ta có một file đầu vào gồm 3 dòng, và đang tìm kiếm một dòng cụ thể (line 2) trong file đó. Nhưng giả sử bạn chỉ muốn lấy những dòng có chứa dạng số nhiều của từ “line”, tức là “lines” thì sao? Và nếu bạn chỉ muốn lấy đúng từ đứng trước nó – kèm theo từ “lines” – nhưng không cần toàn bộ dòng chứa “line x” thì xử lý như thế nào?

Trong trường hợp này, chúng ta có thể sử dụng grep kết hợp với tham số -o (viết tắt của “only”) để chỉ in ra phần phù hợp mà ta cần:

$ grep -o 'lines' test lines $ grep -o '\w\+ lines' test your lines

Bingo! Đầu tiên, ta tìm đúng từ ‘lines’, và nó được in ra. Sau đó, ta bổ sung phía trước một khoảng trắng cùng với biểu thức chính quy để chỉ định như sau (theo ngôn ngữ mô tả giả lập):

  • Tìm một từ (\w) – tức là tập hợp các ký tự chữ và số
  • Với điều kiện từ đó xuất hiện ít nhất một lần hoặc nhiều hơn (\+)
  • Tiếp theo là dấu cách
  • Và kết thúc bằng từ lines

Kết luận

Đọc đến đây, bạn đã được hướng dẫn cách xác định chính xác thư mục chứa script bằng cách kết hợp linh hoạt giữa dirnamepwd, giúp truy xuất đường dẫn tuyệt đối một cách hiệu quả – bất kể script được gọi bằng đường dẫn tương đối hay tuyệt đối. Bên cạnh đó, bạn cũng học được cách tinh chỉnh lệnh grep với tham số -o và biểu thức chính quy để trích xuất chính xác nội dung mong muốn thay vì toàn bộ dòng – một kỹ thuật đơn giản nhưng cực kỳ hữu ích trong xử lý văn bản và phân tích log trong môi trường Bash.

Các ví dụ về mẹo và thủ thuật dòng lệnh Bash hữu ích – Phần 1

Các ví dụ về mẹo và thủ thuật dòng lệnh Bash hữu ích – Phần 2

Các ví dụ về mẹo và thủ thuật dòng lệnh Bash hữu ích – Phần 3

Các ví dụ về mẹo và thủ thuật dòng lệnh Bash hữu ích – Phần 4

Các ví dụ về mẹo và thủ thuật dòng lệnh Bash hữu ích – Phần 5

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *