Giới thiệu về Bash Shell Scripting

Tổng quan chi tiết về cách viết kịch bản cho Bash Shell

Tập lệnh Shell là một cách mạnh mẽ để tự động hóa các tác vụ mà bạn thường xuyên thực thi trên máy tính của mình.

Trong hướng dẫn này, tôi đưa ra một cái nhìn tổng quan sâu rộng về shell scripting và sẽ là tài liệu tham khảo cơ bản cho các hướng dẫn chuyên sâu và nâng cao hơn về cách tạo shell script thực tế.

Kiểm tra của tôigiới thiệu về Bashbài đăng.

Bash cung cấp cho bạn một tập hợp các lệnh kết hợp với nhau có thể được sử dụng để tạo các chương trình nhỏ, theo quy ước chúng ta gọi là script.

Lưu ý sự khác biệt. Chúng tôi không nói lập trình Bash mà chỉ nói kịch bản Bash, và chúng tôi không gọi tập lệnh Bash là “chương trình Bash”. Điều này là do bạn thường có thể đạt đến một mức độ phức tạp nhất định trước khi cảm thấy rằng các tập lệnh của bạn đã vượt quá tầm tay.

Nhưng các tập lệnh Bash rất tuyệt vì bạn không cần bất cứ thứ gì khác ngoài Bash để chạy chúng. Không có trình biên dịch, không có trình thông dịch, chỉ là trình bao của bạn.

Có rất nhiều thứ mà bạn sẽ bỏ lỡ từ các ngôn ngữ lập trình như Perl hoặc JavaScript hoặc Python.

Các biến không có phạm vi, chúng đều là toàn cục, không có thư viện chuẩn, chẳng hạn như bạn không có hệ thống mô-đun. Nhưng ưu điểm là khá lớn: bạn có thể rất dễ dàng gọi bất kỳ công cụ CLI nào giống như khi bạn ở trong shell và cách tiếp cận Unix với việc có nhiều lệnh tiện ích nhỏ thực sự làm cho kịch bản shell trở nên tỏa sáng. Thực hiện các yêu cầu mạng vớiwget, xử lý văn bản bằng cách sử dụngawk, và hơn thế nữa.

Shell scripting là một trong những công cụ mà bạn nên biết, ít nhất là biết cách đọc một chương trình khi bạn nhìn thấy nó và những tiện ích mà nó có thể mang lại cho công việc hàng ngày của bạn.

Hướng dẫn này hướng dẫn bạn lý thuyết và khái niệm về Bash scripting. Tôi sẽ đăng các bài hướng dẫn chi tiết hơn về các kỹ thuật cụ thể hoặc cách giải quyết các vấn đề cụ thể trong tương lai.

Khái niệm cơ bản

Các tập lệnh được lưu trữ trong các tệp. Bạn có thể đặt bất kỳ tên và phần mở rộng nào cho tập lệnh shell, điều đó không quan trọng. Điều quan trọng là nó phải bắt đầu bằng “shebang” ở dòng đầu tiên:

#!/bin/bash

và nó phải là một tệp thực thi.

Một tệp được đặt làm tệp thực thi bằng cách sử dụngchmod, một lệnh tiện ích.

Bạn có thể sử dụng nó như thế này:

chmod u+x myscript

để làm chomyscripttệp thực thi cho người dùng của bạn (Tôi không đi sâu vào lỗ hổng cấp quyền ở đây, nhưng tôi sẽ trình bày chúng sớm).

Bây giờ bạn có thể thực thi tập lệnh nếu bạn đang ở trong cùng một thư mục bằng cách gọi nó./myscripthoặc sử dụng đường dẫn đầy đủ đến nó.

Trong khi học, tôi khuyến khích bạn - khi có thể - sử dụng sân chơi trực tuyếngiống cái này, nó giúp mọi thứ kiểm tra dễ dàng hơn.

Bình luận

Nhận xét là một trong những điều quan trọng nhất khi viết chương trình. Một dòng bắt đầu bằng#biểu tượng là một nhận xét (ngoại trừ dòng shebang mà bạn đã thấy ở trên ở đây).

#!/bin/bash
# this is a comment

Một nhận xét cũng có thể bắt đầu ở cuối dòng:

#!/bin/bash
echo ok # this is a comment

Biến

Bạn có thể đặt các biến bằng cách sử dụng=nhà điều hành:

name=value

Ví dụ:

ROOM_NUMBER=237
name=Flavio
nickname="Flavio"

Bạn có thể in một biến bằng cách sử dụngecholệnh tích hợp sẵn và viết trước một$đến tên var:

echo $ROOM_NUMBER
echo $name

Các nhà khai thác

Bash triển khai một số toán tử số học thường được sử dụng trên các ngôn ngữ lập trình:

  • +thêm vào
  • -trừ đi
  • *nhân
  • /chia
  • %modulo (phần còn lại của phép chia)
  • **lũy thừa

Bạn có thể so sánh các giá trị bằng cách sử dụng

  • <
  • <=
  • ==
  • >=
  • >

Bạn cũng có thể sử dụng các toán tử so sánh sau:

  • -ltthấp hơn
  • -gtlớn hơn
  • -lethấp hơn hoặc bằng
  • -gelớn hơn hoặc bằng
  • -eqtương đương với
  • -nekhông bằng

Theo cách này:

#!/bin/bash
age=23
minimum=18
if test $age -lt $minimum
then
  echo "Not old enough"
fi

Toán tử logic:

  • &&logic AND
  • ||logic HOẶC

Các phím tắt này cho phép thực hiện một phép toán số học và sau đó là một phép gán:

  • +=
  • -=
  • *=
  • /=
  • %=

Có một số toán tử khác, nhưng đó là những toán tử phổ biến nhất.

Bạn có thể in bất cứ thứ gì ra màn hình bằng cách sử dụngechochỉ huy:

#!/bin/bash
echo "test"
echo test
echo testing something

Điều kiện logic

AND: đánh giá thành0(không) nếu cả haicommandanothercommandthực hiện và trở lại0. Trả về số không trong các lệnh shell có nghĩa là lệnh đã thành công. Thông báo lỗi được xác định bằng giá trị trả về khác 0.

command && anothercommand

HOẶC: đánh giá thành0(không) nếu ít nhất một trong sốcommandanothercommandthực hiện và trở lại0.

command || anothercommand

KHÔNG: đảo ngược giá trị trả về logic củacommand:

! command

Cấu trúc điều khiển

Trong bạn có thể sử dụng một số cấu trúc điều khiển mà bạn có thể quen thuộc:

Câu lệnh if / else

Đơn giảnif:

if condition
then
  command
fi

ifsau đóelse:

if condition
then
  command
else
  anothercommand
fi

Lồng nhauif- sau đó -else:

if condition
then
  command
elif
  anothercommand
else
  yetanothercommand
fi

Bạn có thể giữelsetrên cùng một dòng bằng cách sử dụng dấu chấm phẩy:

if condition ; then
  command
fi

Thí dụ:

#!/bin/bash
DOGNAME=Roger
if [ "$DOGNAME" == "" ]; then
  echo "Not a valid dog name!"
else
  echo "Your dog name is $DOGNAME"
fi

Chú ý dấu ngoặc? Chúng ta phải thêm dấu ngoặc khi chúng ta phải thực hiện bất kỳ loại đánh giá nào của một biểu thức boolean.

Vòng lặp

Trong khi lặp lại

Trong khiconditiongiải quyết thành một giá trị thực, chạycommand

while condition
do
  command
done

Cho đến khi

Cho đến khiconditiongiải quyết thành một giá trị thực, chạycommand

until condition
do
  command
done

Tại

Lặp lại danh sách và thực hiện lệnh cho từng mục

for item in list
do
  command
done

Ngắt và tiếp tục

Bên trong các vòng lặp, bạn có thể sử dụngbreakcontinueđể phá vỡ hoàn toàn vòng lặp hoặc chỉ bỏ qua lần lặp hiện tại.

Trường hợp

Cấu trúc kiểm soát trường hợp cho phép bạn chọn các tuyến đường khác nhau tùy thuộc vào một giá trị.

case value in
  a)
    command
    #...
    ;;
  b)
    command
    #...
    ;;
esac

Thích vớifi,esackết thúc cấu trúc trường hợp và như bạn có thể nhận thấy nócasenói ngược.

Chúng tôi thêm dấu chấm phẩy kép sau mỗi trường hợp.

A*)trường hợp sẽ xử lý tất cả các trường hợp không được thể hiện rõ ràng. Sử dụng một|biểu tượng bạn có thể thể hiện nhiều lựa chọn cho một trường hợp duy nhất.

Thí dụ:

#!/bin/bash
read -p "How many shoes do you have?" value
case $value in
  0|1)
    echo "Not enough shoes! You can't walk"
    ;;
  2)
    echo "Awesome! Go walk!"
    #...
    ;;
  *)
    echo "You got more shoes than you need"
    #...
    ;;
esac

Lựa chọn

Aselectcấu trúc hiển thị cho người dùng một menu các lựa chọn để chọn:

select item in list
do
  command
done

Thí dụ:

#!/bin/bash
select breed in husky setter "border collie" chiwawa STOP
do
  if [ "$breed" == "" ]; then
    echo Please choose one;
  else
    break
  fi
done

echo “You chose $breed

Điều kiện thử nghiệm

Tôi đã sử dụng thuật ngữ nàyconditiontrong các cấu trúc điều khiển trên.

Bạn có thể dùngtestLệnh tích hợp sẵn Bash để kiểm tra một điều kiện và trả về giá trị true (0) hoặc giá trị sai (không phải0).

Đây là một ví dụ:

#!/bin/bash
if test "apples" == "apples"
then
  echo Apples are apples
fi

if ! test “apples” == “oranges” then echo Apples are not oranges fi

Đọc đầu vào từ dòng lệnh

Bạn có thể làm cho các tập lệnh của mình trở nên tương tác bằng cách sử dụngreadlệnh cài sẵn. Lệnh này đọc một dòng từ đầu vào chuẩn và nó có thể định dạng đầu vào theo cách rất linh hoạt.

Cách sử dụng đơn giản nhất là:

echo "Age:"
read age

điều này sẽ in ra “Tuổi:” và bạn có thể nhập một số, nhấn enter và số đó sẽ được gán choageBiến đổi.

Các-ptùy chọn củareadcung cấp lời nhắc tích hợp và đặt đầu vào trongageBiến đổi:

read -p "Age: " age

Cácreadlệnh có nhiều tùy chọn khác mà bạn có thể kiểm tra bằng cách gõhelp readtrong Bash.

Thêm tùy chọn

Các tùy chọn được chỉ định bằng dấu gạch ngang, theo sau là một chữ cái, như sau:

ls -a
driveCar -b "Ford"

Trong mã của bạn, bạn sử dụng lệnh tích hợpgetoptsđể phân tích cú pháp các tùy chọn và nhận giá trị.

Nếu chúng tôi chấp nhận các tùy chọnab, chúng tôi ăngetopts abđến một vòng lặp trong khi.

Nếu tùy chọnbchấp nhận một giá trị, chúng tôi thêm dấu hai chấm:sau nó, vì vậy chúng tôi định dạnggetoptsgọi như thế này:getopts ab: arg

Đây là một đoạn mã:

while getopts xy: arg
do
  case $arg in
    x) echo "Option $arg enabled" ;;
    y) echo "The value of $arg is $OPTARG" ;;
    esac
done

Trong tập lệnh này,$OPTARGđược tự động gán ký tự tùy chọn. Chúng tôi nóigetoptstùy chọn nào chúng tôi chấp nhận và chúng tôi xử lý từng trường hợp riêng biệt.

Các lỗi được xử lý tự động bởigetopts. Chúng ta có thể chọn tự xử lý các thông báo lỗi bằng cách thêm dấu hai chấm trước:trước định nghĩa đối số:getopts :xy: arg.

Sau đó, chúng tôi cũng xử lý\?:các trường hợp. Tùy chọn đầu tiên được gọi khi chúng tôi vượt qua một tùy chọn không hợp lệ và tùy chọn thứ hai được gọi khi chúng tôi bỏ lỡ một tùy chọn:

while getopts :xy: arg
do
  case $arg in
    x) echo "Option $arg enabled" ;;
    y) echo "The value of $arg is $OPTARG" ;;
    :) echo "$0: Must supply an argument to -$OPTARG." >&2
       exit 1 ;;
    \?) echo "Invalid option -$OPTARG ignored." >&2 ;;
    esac
done

Bây giờ nếu bạn bỏ lỡ thêm một đối số, các thông báo lỗi sẽ khác.

Làm việc với các tham số

Bên trong một tập lệnh, bạn có thể truy cập bất kỳ tham số nào đã được chuyển vào thời điểm gọi. Bạn truy cập chúng bằng cách sử dụng$0,$1,$2và như vậy, tùy thuộc vào vị trí, nơi$0là tên của lệnh và tăng số vị trí của tham số được tăng lên. Sau vị trí 9, bạn cần dấu ngoặc nhọn:${10},${11}

Ví dụ chạy cái nàystartCarkịch bản:

#!/bin/bash
echo $0
echo $1

như./startCar fiestasẽ in

./startCar
fiesta

Cái đặc biệt$*cú pháp in tất cả các tham số và$#số lượng tham số được truyền:

#!/bin/bash
echo $# $*
./test.sh Milan Florence Rome
3 Milan Florence Rome

Tách các tùy chọn khỏi các tham số

Nếu bạn có cả hai tùy chọn và thông số, bạn cần phải tách chúng ra. Bạn làm điều này với dấu gạch ngang:

driveCar -m "Ford Fiesta" - Milan Florence Rome

Làm việc với chuỗi

Cho một chuỗi:

dogname="Roger"

Bạn có thể lấy độ dài của nó bằng cách sử dụng${#dogname}

Luôn sử dụng dấu ngoặc kép xung quanh các chuỗi, khi làm việc với chúng, để tránh Bash giải thích các ký tự đặc biệt bên trong chúng.

Bạn có thể so sánh 2 chuỗi bằng cách sử dụng=hoặc là==toán tử, nó giống nhau:

"$dogname" = "$anotherdogname"
"$dogname" == "$anotherdogname"

Nó không phải là một nhiệm vụ vì các khoảng trống xung quanh=.

Bạn cũng có thể kiểm tra sự bất bình đẳng:

"$dogname" != "$anotherdogname"

Mảng

Mảng là một danh sách các mục, được khai báo bên trong dấu ngoặc đơn:

breeds=(husky setter "border collie" chiwawa)

Bạn có thể tham chiếu bất kỳ mục nào bên trong một mảng bằng cách sử dụng dấu ngoặc vuông:

breeds[0]
breeds[1]

và bạn có thể nhận được tổng số mục bằng cú pháp đặc biệt này:

${#breeds[@]}

Các lệnh tích hợp

Cho đến nay, bạn đã thấy một số lệnh tích hợp sẵn, như sau:

  • test
  • read
  • echo

Bash có một số trong số họ. Bạn có thể thấy tất cả chúng bằng cách gọihelpvà sau đó, bạn có thể tìm trợ giúp cho từng lệnh bằng cách sử dụng ví dụ:help read.

Chức năng

Cũng giống như trong JavaScript hoặc bất kỳ ngôn ngữ lập trình nào khác, bạn có thể tạo các đoạn mã nhỏ có thể tái sử dụng, đặt tên cho chúng và gọi chúng khi bạn cần.

Bash gọi họchức năng.

Bạn xác định một hàm với

function name {

}

Thí dụ:

function cleanFolder {

}

và bạn gọi nó như thế này:

cleanFolder

Bạn có thể truyền tham số cho các thư mục mà không cần khai báo chúng - bạn chỉ cần tham chiếu chúng là$1,$2v.v. Giống như bạn làm đối với các tham số tập lệnh:

function cleanFolder {
  echo "Clean folder $1"
}
cleanFolder "/Users/flavio/Desktop"

Tải xuống miễn phí của tôiSổ tay lệnh Linux


Thêm các hướng dẫn về cli: