Câu 1n=$(grep -c error log.txt) đưa gì vào biến n?
Kết hợp lệnh — Rẽ nhánh theo kết quả grep / awk
Bài viết này là một phần của Khóa học Linux, giúp bạn thành thạo từ đầu những kỹ năng Linux thực tiễn, từ các lệnh cơ bản đến lập trình shell script.
Trong script, đưa số đếm vào biến bằng n=$(grep -c ERROR access.log), lấy tổng bằng total=$(awk '{s+=$1} END{print s}'), rồi rẽ nhánh bằng if [ "$n" -ge 2 ] — một script quét log được minh họa và viết ngay trên terminal trong trình duyệt.
Gọi lệnh bên trong script — pipe và thay thế lệnh
Sức mạnh thật sự của shell script nằm ở chỗ bạn kết hợp được các lệnh thông thường như `grep` `awk` `sed` `sort` `wc` ngay bên trong nó.
Ngay trong script, bạn cũng nối các lệnh bằng pipe | như khi gõ ở dấu nhắc, và lấy đầu ra của chúng vào biến bằng thay thế lệnh $(cmd).
Viết n=$(grep -c error log.txt) thì số dòng khớp mà grep -c đếm được sẽ vào biến n.
Bạn cũng đưa được một kết quả tổng hợp vào biến, như total=$(awk '{s+=$1} END{print s}' f).
Khi kết quả của một lệnh đã nằm trong biến, bạn dùng giá trị đó để thay đổi cách script hoạt động.
printf 'INFO ok\nERROR disk\nINFO ok\nERROR cpu\n' > sys.log # tạo tệp dữ liệu mẫu
vi count.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# n=$(grep -c ERROR sys.log)
# echo "ERROR count: $n"
chmod +x count.sh
./count.sh # ERROR count: 2
grep -c đếm được đi vào biến n, còn if rẽ sang cảnh báo khi nó từ 2 trở lên và in OK trong các trường hợp còn lại.| Cú pháp | Ý nghĩa | Ví dụ |
|---|---|---|
n=$(grep -c pat f) | Đưa số dòng khớp vào biến n | n=$(grep -c error log.txt) |
$(cmd | cmd) | Lấy kết quả của một pipeline vào biến | top=$(sort log.txt | head -1) |
if [ "$n" -ge 2 ]; then … | Rẽ nhánh tùy theo số đếm có từ 2 trở lên hay không | if [ "$n" -ge 2 ]; then echo warn; fi |
Tính tổng rồi hành động theo kết quả — awk và rẽ nhánh
Ngoài số đếm, bạn còn cộng được các con số lại rồi quyết định dựa trên tổng.
total=$(awk '{s+=$1} END{print s}' f) cộng cột 1 của mọi dòng rồi đưa tổng vào biến total.
Khi bạn muốn biết số lần xuất hiện của từng từ, hãy dùng sort f | uniq -c: uniq chỉ gộp được các dòng trùng nằm liền nhau, nên phải sort trước rồi mới đếm, sau đó lấy kết quả đó vào biến bằng $(...).
So tổng với một ngưỡng, như if [ "$total" -gt 100 ]; then …, thì bạn ra được quyết định kiểu "cảnh báo khi tổng vượt quá một mức".
Gộp phần tính tổng và rẽ nhánh vào cùng một script và bạn có một công cụ thiết thực đọc dữ liệu rồi xác định tình hình đang ra sao.
printf '40\n30\n50\n' > sales.txt # dữ liệu số 1 cột
vi sum.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# total=$(awk '{s+=$1} END{print s}' sales.txt)
# if [ "$total" -gt 100 ]; then
# echo "total $total: goal met"
# else
# echo "total $total: not met"
# fi
chmod +x sum.sh
./sum.sh # total 120: goal met
printf 'a\na\nb\n' > tags.txt # tệp dữ liệu mẫu có các từ lặp lại
sort tags.txt | uniq -c # sắp xếp trước rồi đếm
# đầu ra:
# 2 a
# 1 b
if so total mà awk cộng được với ngưỡng 20, rẽ sang needs action khi vượt và within limit khi không vượt.| Cú pháp | Ý nghĩa | Ví dụ |
|---|---|---|
awk '{s+=$1} END{print s}' f | Cộng cột 1 | awk '{s+=$1} END{print s}' nums.txt |
sort f | uniq -c | Sắp xếp trước để các dòng trùng nằm liền nhau rồi đếm | sort tags.txt | uniq -c |
if [ "$total" -gt N ]; then … | Rẽ nhánh bằng cách so tổng với ngưỡng N | if [ "$total" -gt 100 ]; then … |
Điều hướng đầu ra và lỗi — > và 2>
Đôi khi bạn muốn giữ kết quả của script trong một tệp thay vì để trên màn hình.
./scan.sh > report.txt ghi đầu ra thông thường (đầu ra chuẩn) vào report.txt.
Đưa thông báo lỗi sang lỗi chuẩn bằng echo "..." 1>&2, rồi ./scan.sh > report.txt 2> error.log cho phép bạn giữ kết quả bình thường và lỗi trong hai tệp riêng.
vi job.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# echo "processing started" # đầu ra chuẩn
# echo "note: input was empty" 1>&2 # lỗi chuẩn
chmod +x job.sh
./job.sh > out.txt 2> err.txt # đưa đầu ra và lỗi sang hai tệp riêng
cat out.txt # processing started
cat err.txt # note: input was empty
> report.txt còn lỗi chuẩn đi vào 2> error.log, nên hai thứ nằm ở hai tệp riêng.| Cú pháp | Ý nghĩa | Ví dụ |
|---|---|---|
cmd > out | Ghi đầu ra chuẩn vào một tệp | ./scan.sh > report.txt |
echo "…" 1>&2 | Đưa một thông báo sang lỗi chuẩn | echo "failed" 1>&2 |
cmd > out 2> err | Điều hướng đầu ra và lỗi sang hai tệp riêng | ./scan.sh > report.txt 2> error.log |
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2if [ "$n" -ge 2 ]; then … làm gì?
Câu 3Trong ./scan.sh > report.txt 2> error.log, 2> điều hướng cái gì?