Bash/Shell cơ bản

  1. Lập trình

Với các ngôn ngữ lập trình phổ biến như C hay Java, chúng ta cần rất nhiều dòng lệnh cùng các câu lệnh phức tạp để chạy một chương trình. Đó là chưa kể đến việc cần cài đặt thêm IDE để có thể viết được một chương trình hoàn chỉnh.

Vậy sẽ ra sao nếu như chúng ta có thể viết những dòng code ngắn gọn, lưu vào một file và có thể thực thi dễ dàng mà không cần cài đặt gì. Trong bài viết này, tôi sẽ giới thiệu với mọi người cách sử dụng bash shell cơ bản.

I. Giới thiệu

  • Kịch bản Shell (Shell script) là một chương trình máy tính được thiết kế để chạy trên nền tảng Unix/Linux. Bao gồm các loại:
  • The Bourne Shell
  • The C Shell
  • The Korn Shell
  • The GNU Bourne-Again Shell (Bash Shell)
  • Shell là một trình diễn dịch các dòng lệnh và các thao tác được viết bởi kịch bản shell bao gồm xử lý file và thực thi các chương trình.
  • Bash shell là shell tiêu chuẩn và thông dụng nhất, là một ngôn ngữ kịch bản cho phép chúng ta sử dụng shell và tự động hoá rất nhiều tác vụ bao gồm nhiều dòng lệnh.
  • Bash shell đã và đang được ứng dụng nhiều trong Machine Learning nhờ sự tiện dụng của mình trong việc code và xử lý dữ liệu.

II. So sánh với ngôn ngữ lập trình

1/Ngôn ngữ lập trình

  • Là một ngôn ngữ trên cơ sở biên dịch (compiler-based language). Cần được biên dịch thành các file có thể thực thi (ví dụ file.exe).
  • Được thiết kế với đầy đủ tính chất của một ngôn ngữ.
  • Phức tạp khi code, cần rất nhiều dòng lệnh cho một hàm.
  • Ví dụ: C, C++, Java

2/Ngôn ngữ kịch bản

  • Là một ngôn ngữ trên cơ sở diễn dịch (interpreter-based language). Trình diễn dịch sẽ đọc các câu lệnh trong file nguồn và thực thi từng câu lệnh.
  • Được thiết kế để có thể code nhanh và đơn giản.
  • Dễ dàng khi code, chỉ cần một số dòng lệnh ngắn gọn trong mỗi hàm.
  • Ví dụ: Shell, Python, Javascript

III. Một số kiến thức cơ bản

1/Thực thi chương trình đầu tiên

  • Dòng lệnh đầu tiên bắt buộc có là:

#!/bin/bash

Dòng lệnh này là một shebang. Câu lệnh này nói cho shell chương trình được chọn để diễn dịch khi thực thi file (trong trường hợp này, file sẽ được thực thi bởi bash shell).

chmod +x scriptname

Cấp phát quyền thực thi cho file.

./scritpname

Câu lệnh trên là câu lệnh thực thi chương trình.

  • Ví dụ chương trình:

#!/bin/bash
echo "Hello World"


Khi thực thi, chương trình sẽ in dòng "Hello World" vào standard output (terminal).

2/Biến

  • Trong Bash Shell, chúng ta có thể sử dụng biến như trong các ngôn ngữ lập trình khác. Giá trị của biến luôn được lưu trữ ở dạng xâu (String), nhưng trong một số công thức toán học, giá trị của biến được chuyển về dạng số để tính toán.
  • Chúng ta không cần khai báo biến, chỉ cần gán giá trị cho một biến là xong.
  • Ví dụ:

#!/bin/bash
STR="Hello World!"
echo $STR


Dòng thứ 2 tạo một biến tên STR và gán giá trị "Hello World!" cho biến đó. Sau đó, chúng ta đặt kí tự '$' trước tên biến để lấy giá trị của biến.

  • Chú ý!!! Ngôn ngữ Shell không gán kiểu giá trị cho các biến. Vì vậy, một biến có thể giữ giá trị số hoặc kí tự.

#!/bin/bash
count=0
count=Sunday


Tuy nhiên, việc thay đổi kiểu giá trị của một biến có thể dẫn đến khó khăn cho người viết cũng như người sửa chương trình về sau. Vậy nên, mọi người chỉ nên sử dụng một kiểu giá trị cho một biến trong chương trình.

3/Công thức số học

  • Câu lệnh "let" được cùng để thực hiện các hàm tính toán.

#!/bin/bash
let X=10+2*7
echo $X


Chương trình sẽ in giá trị của X là 24.

  • Ngoài ra, ta có thể sử dụng $[expression] hoặc $((expression)).

#!/bin/bash
echo "$((123+20))"


Chương trình in ra 143.

#!/bin/bash
VAL=$[123+20]
echo "$[123*$VAL]"


Chương trình in ra 17589.

4/Câu lệnh điều kiện

  • Câu lệnh điều kiện giúp chúng ta quyết định có thực hiện một hành động hay không, quyết định này được đưa ra sau khi xét qua một điều kiện.
  • Câu lệnh có dạng:

if [ expression ];
then
    statements
elif [ expression ];
then
    statements
else
    statements
fi


"elif" (else if) và "else" có thể không cần thiết trong một vài trường hợp.

  • Chú ý!!! Bắt buộc phải có khoảng trống (space) sau dấu '[', trước dấu ']' và giữa các toán tử, toán hạng.

5/Các điều kiện

  • Một điều kiện có thể là: So sánh xâu, so sánh số, kiểm tra file hoặc các biểu thức logic.
  • So sánh xâu:

= hai chuỗi có bằng nhau không?

!= hai chuỗi có khác nhau không?

-n chuỗi có độ dài lớn hơn 0?

-r chuỗi có độ dài bằng 0?

#!/bin/bash
echo "Enter your login name: "
read name
if [ "$name" = "$USER" ];
then
echo "Hello, $name. How are you today?"
else
echo "You are not $USER, so who are you?"
fi

  • So sánh số:

-eq hai số có bằng nhau không?

-ge số thứ nhất có lớn hơn hoặc bằng số thứ hai?

-le số thứ nhất có nhỏ hơn hoặc bằng số thứ hai?

-ne hai số có khác nhau không?

-gt số thứ nhất có lớn hơn số thứ hai?

-lt số thứ nhất có nhỏ hơn số thứ hai?

#!/bin/bash
echo "Enter a number: "
read i
if [ $i -eq 1 ];
then
echo "Your input is 1."
else
echo "Your input is not 1."
fi
  • Kiểm tra file:

-d đường dẫn có phải là một thư mục không?

-f đường dẫn có phải một file không?

-e tên file có tồn tại không?

-r file hoặc thư mục có được cấp quyền đọc (read) không?

-s độ dài của file có lớn hơn 0?

-w file hoặc thư mục có được cấp quyền viết (write) không?

-x file hoặc thư mục có được cấp quyền thực thi (execute) không?

  • Biểu thức logic:

! NOT

-a AND

-o OR

#!/bin/bash
echo "Enter a number: "
read i
if [ $i -eq 1 -o $i -eq 0 ];
then
echo "$i is either 1 or 0."
else
echo "$i is neither 1 nor 0."
fi

Chương trình kiểm tra dữ liệu nhập vào có phải là 0 hoặc 1.

6/Tham số

  • Tham số vị trí được truyền vào trong câu lệnh thực thi chương trình.
  • Ví dụ:
./scritpname 14 15

Câu lệnh truyền vào chương trình hai tham số $1 = 14 và $2 = 15.

  • Một số tham số đặc biệt:

$# số lượng tham số truyền vào

$0 trả về tên của kịch bản đang chạy và vị trí của nó

$* trả về tất cả các tham số đã truyền vào

$@ trả về chuỗi các tham số đã truyền vào

  • Ví dụ:

#!/bin/bash
if [ $# -eq 1 ]
then
echo "You entered 1 parameter and it is $1."
else
echo "You entered 0 or more than 1 parameter."
fi


Chương trình kiểm tra số lượng tham số đã truyền vào.

7/Câu lệnh vòng lặp

  • Câu lệnh "for" được sử dụng để duyệt một chuỗi các giá trị của biến.
for var in list
do
statements
done


Khi thực thi, biến var sẽ được lần lượt gán các giá trị trong danh sách (list).

  • Ví dụ:
#!/bin/bash
let sum=0
for num in 1 2 3 4 5
do
let "sum = $sum + $num"
done
echo $sum


Chương trình tính tổng các số từ 1 đến 5, in ra kết quả là 15.

  • Sử dụng mảng trong vòng lặp:
  • Trong bash shell, chúng ta có thể sử dụng mảng để lưu trữ dữ liệu. Có 2 cách để tạo một mảng:

#!/bin/bash
pet[0]=dog
pet[1]=cat
pet[2]=fish

#!/bin/bash
pet=(dog cat fish)


  • Để lấy ra một giá trị trong mảng, ta sử dụng: ${arrayname[i]}

Ví dụ: ${pet[0]} là giá trị thứ nhất trong mảng, mang giá trị "dog"

  • Để lấy ra tất cả các giá trị của một mảng, ta sử dụng: ${arrayname[*]}
#!/bin/bash

pet=(dog cat fish)

for x in ${pet[*]}
do
echo $x
done


Chương trình trên in ra tất cả các giá trị của mảng pet.

*** Ngoài ra, với bash shell, người dùng có thể sử dụng câu lệnh rẽ nhánh case, vòng lặp while và các hàm như trong các ngôn ngữ lập trình khác.

Câu lệnh rẽ nhánh case:

#!/bin/bash
echo "Enter a number 0 < x < 10:"
read x
case $x in
1) echo "Value of x is 1.";;
2) echo "Value of x is 2.";;
3) echo "Value of x is 3.";;
4) echo "Value of x is 4.";;
5) echo "Value of x is 5.";;
6) echo "Value of x is 6.";;
7) echo "Value of x is 7.";;
8) echo "Value of x is 8.";;
9) echo "Value of x is 9.";;
*) echo "Unregonized value.";;
esac

Vòng lặp while:
#!/bin/bash
echo "Enter a number:"; read x
let sum=0; let i=1
while [ $i -le $x ]; do
let "sum = $sum + $i"
let i=$i+1
done
echo "The sum of the first $x numbers is: $sum"

Chương trình sử dụng hàm:
#!/bin/bash

# Define your function here
Hello () {
echo "Hello World"
}

# Invoke your function
Hello


8/Một chương trình trong bash shell

Đây là chương trình kiểm tra số nguyên tố do người dùng nhập vào.

#!/bin/bash
if [ $# -ne 1 ]; then
echo "You should input a number."
else
if [ $1 -le 1 ]; then
echo "$1 is not a prime number."
exit 0
fi
x=$(echo "scale=2;sqrt($1)") | bc)
x=$(x%.*)
for i in $(seq 2 $x); do
a=$(($1 % $i))
if [ $a -eq 0 ]; then
echo "$1 is not a prime number."
exit 0
fi
done
echo "$1 is a prime number."
fi


IV. Kiến thức nâng cao

1/Điều hướng input/output

  • Chương trình có mặc định input tiêu chuẩn được nhận từ một thiết bị, như bàn phím. Output tiêu chuẩn là terminal.
  • Linux có hỗ trợ người dùng trong việc điều hướng input, output khi cần sử dụng một input, output khác.
  • Ví dụ:
#!/bin/bash
who > users


Chương trình lưu thông tin người dùng vào file "users".

  • Để nhận input, ta sử dụng kí hiệu <
  • Để ghi đè vào file, ta sử dụng >
  • Để ghi thêm vào file, ta sử dụng >>

2/Regular Expressions

  • Regular Expressions (Regexs) được sử dụng để tìm kiếm văn bản hoặc xử lí dữ liệu xâu.
  • Một regex có thể gồm:
  • Một chuỗi kí tự. Ví dụ [ae] có thể gắn với một kí tự 'a' hoặc một kí tự 'e'. Ta có thể sử dụng gr[ae]y để tìm kiếm hai từ là "gray" hoặc "grey"
  • Một anchor (mỏ neo). Ví dụ $ gắn với vị trí ở sau kí tự cuối cùng trong xâu. "c$" có thể gắn với "abc" vì 'c' ở vị trí cuối trong xâu. Nhưng "a$" thì không thể gắn với xâu trên.
  • Các modifiers. Ví dụ (?i) khiến cho regex không phân biệt chữ hoa, chữ thường. "(?i)te(?-i)st" có thể gắn với ""test" hoặc "TEst", nhưng không thể gắn với "teST" hay "TEST".

3/sed và awk

a. sed

  • sed là một công cụ biên tập các dòng dữ liệu. sed nhận các văn bản đầu vào, thực thi một số lệnh trên từng dòng một, và sau đó trả dữ liệu ra về output tiêu chuẩn hoặc một file.
  • Một số lệnh của sed:

[address-range]/p ___ in ra dòng

[address-range]/d ___ xóa dòng

s/pattern1/pattern2/___ thay đổi vị trí đầu tiên của pattern1 thành pattern2

[address]i pattern Filename ___ chèn pattern vào vị trí nói đến trong file

g ___ áp dụng thay đổi cho tất cả các vị trí của pattern

  • Ví dụ:
#!/bin/bash
sed -i 's/foo/bar/g' hello.txt
cat hello.txt
https://cdn.noron.vn/2018/10/19/682b2307354c9a36f249f79f7fbc86bf_1024.pnghttps://cdn.noron.vn/2018/10/19/d1efd3c2a8db25f8b76f2a5231dbd5fc_1024.png

Chương trình thay đổi các từ "foo" thành "bar" trong file "hello.txt"

b. awk

  • awk là một công cụ xử lý văn bản. awk chia nhỏ mỗi dòng thành các trường nhỏ (fields) và xử lí.
  • Ví dụ:
#!/bin/bash
# $1 is field #1, $2 is field #2, etc.
echo one two | awk '{print $1}'
# one
echo one two | awk '{print $2}'
# two

# But what is field #0 ($0)?
echo one two | awk '{print $0}'
# one two
# All the fields!

awk '{print $3}' $filename
# Prints field #3 of file $filename to stdout.
awk '{print $1 $5 $6}' $filename
# Prints fields #1, #5, and #6 of file $filename.

awk '{print $0}' $filename
# Prints the entire file!


*** Một số tài liệu tham khảo:

Advanced Bash-Scripting Guide:

Tutorials point:

Vietjack (bản tiếng Việt của Tutorials point):

PCWDLD

Từ khóa: 

ngôn ngữ lập trình

,

học lập trình

,

công nghệ

,

kiến thức

,

lập trình

Bài viết đầy đủ và chi tiết. Đọc xong là có thể code bash shell ngay đươc.

Trả lời

Bài viết đầy đủ và chi tiết. Đọc xong là có thể code bash shell ngay đươc.