Tìm hiểu các shell và so sánh các sell

Ở trong buổi học này, chúng tôi sẽ trình bày vài điều cơ bản trong việc sử dụng bash như một ngôn ngữ kịch bản và giới thiệu một số công cụ của shell được sử dụng thường xuyên trên môi trường dòng lệnh trong các công việc hằng ngày của bạn.

Shell Scripting - Ngôn ngữ kịch bản Shell

Chúng ta đã làm quen với việc thực hiện các lệnh bằng shell [vỏ] và pipe [liên kết] chúng lại với nhau thành một quy trình. Tuy nhiên, trong một vài trường hợp, bạn sẽ cần phải thực thi hàng loạt câu lệnh và sử dụng các cấu trúc điều khiển như câu điền kiện hoặc vòng lặp.

Ngôn ngữ shell là bước tiếp theo để có thể sử dụng những thứ phức tạp hơn. Hầu hết các shell đều có một ngôn ngữ kịch bản riêng với những cú pháp riêng biệt để tương tác với biến, cấu trúc điều khiển.Điều đặc biệt khiến ngôn ngữ shell khác biệt khi so sánh chúng với các ngôn ngữ kịch bản khác chính là ngôn ngữ shell đã được tối ưu cho việc thực thi các tác vụ liên quan tới shell [ở môi trường dòng lệnh]. Do đó, việc tạo quy trình cho lệnh [pipe], lưu kết quả vào file, đọc dữ liệu từ thiết bị nhập chuẩn là những thứ nguyên thuỷ trong khi viết shell, điều này khiến shell script dễ dàng để sử dụng hơn là những ngôn ngũ kịch bản tổng quát. Ở trong phần này chúng ta sẽ sử dụng bash để lập trình shell vì bash rất phổ biến.

Ghi chú [người dịch]:

  • pipeline: Đối với ngành khoa học máy tính, một pipeline là một sự liên kết các tác vụ được sắp xếp sao cho đầu ra của một tác vụ trong quy trình sẽ là đầu vào của tác vụ tiếp theo. Các bạn có thể hiểu pipeline là quy trình. pipe là cách kết nối các tác vụ để tạo nên một pipeline. Trong ngữ cảnh của shell, các tác vụ này có thể hiểu đơn giản là các command [lệnh].

Để gán giá trị cho biến bằng bash, sử dụng cú pháp

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

1 và truy cập giá trị của biến bằng cú pháp

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

2. Lưu ý

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

3 sẽ không chạy bởi vì câu lệnh sẽ được biên dịch thành việc gọi chương trình

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

4 với đối số là

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

5 và

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

6. Tóm lại, dấu khoảng cách đóng vai trò dấu phân cách các đối số trong các ngôn ngữ shell. Việc này có thể sẽ hơi khó hiểu và gây nhầm lẫn ở giai đoạn đầu, nên hãy luôn kiểm tra việc này.

Chuỗi có thể được khai báo bằng dấu

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

7 và

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

8 trong bash, nhưng chúng không bằng nhau. Chuỗi được khai báo bằng

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

7 là chuỗi theo nghĩa đen [giá trị cụ thể] và sẽ không được thay thế bằng các giá trị của biến, trong khi chuỗi được khai báo bằng

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

8 thì có.

foo=bar
echo "$foo"
# prints bar
echo '$foo'
# prints $foo

Như hầu hết các ngôn ngữ lập trình khác, bash cũng hỗ trợ các cấu trúc điều khiển như

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

1,

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

2,

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

3 và

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

4. Và tất nhiên,

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

5 hỗ trợ các hàm nhận vào các đối số và thực hiện các tác vụ. Đây là một ví dụ về hàm có chức năng là tạo một thư mục và

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

6 vào nó.

mcd [] {
    mkdir -p "$1"
    cd "$1"
}

Ở đây

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

7 mang ý nghĩa là đối số được truyền vào đầu tiên cho hàm. Không như các ngôn ngữ khác,

false || echo "Oops, fail"
# Oops, fail
true || echo "Will not be printed"
#
true && echo "Things went well"
# Things went well
false && echo "Will not be printed"
#
true ; echo "This will always run"
# This will always run
false ; echo "This will always run"
# This will always run

5 sử dụng một tập hợp các biến đặc biệt để chỉ đến các đối số, mã lỗi và các biến liên quan. Ở dưới là một danh sách của chúng. Các bạn có thể tìm một danh sách đầy đủ và chi tiết hơn ở đây.

  • false || echo "Oops, fail"

    Oops, fail

    true || echo "Will not be printed"

    true && echo "Things went well"

    Things went well

    false && echo "Will not be printed"

    true ; echo "This will always run"

    This will always run

    false ; echo "This will always run"

    This will always run

    9 - Tên của shell hoặc tên của shell script
  • false || echo "Oops, fail"

    Oops, fail

    true || echo "Will not be printed"

    true && echo "Things went well"

    Things went well

    false && echo "Will not be printed"

    true ; echo "This will always run"

    This will always run

    false ; echo "This will always run"

    This will always run

    7 tới

    #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    1 - Các đối số của lệnh

    false || echo "Oops, fail"

    Oops, fail

    true || echo "Will not be printed"

    true && echo "Things went well"

    Things went well

    false && echo "Will not be printed"

    true ; echo "This will always run"

    This will always run

    false ; echo "This will always run"

    This will always run

    7 là đầu tiên và tiếp tục.
  • #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    3 - Tất cả đối số
  • #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    4 - Số lượng đối số
  • #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    5 - Mã kết quả của lệnh trước [thành công hay thất bại]
  • #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    6 - PID [Process identification number ] của lệnh
  • #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    7 - Chỉ đến lệnh phía trước, tính cả tham số. Một cách sử dụng cơ bản của nó là thực hiện lệnh nếu lệnh trước đó thất bại bởi vì thiếu quyền truy cập[permission denied]. Bạn có thể tái thực hiện lệnh với quyền sudo bằng cách

    #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    8.
  • #!/bin/bash echo "Starting program at $[date]" # Date will be substituted echo "Running program $0 with $# arguments with pid $$" for file in "$@"; do

    grep foobar "$file" > /dev/null 2> /dev/null  
    # When pattern is not found, grep has exit status 1  
    # We redirect STDOUT and STDERR to a null register since we do not care about them  
    if [[ $? -ne 0 ]]; then  
        echo "File $file does not have any foobar, adding one"  
        echo "# foobar" >> "$file"  
    fi  
    
    done

    9 - Đối số cuối cùng của lệnh phía trước. nếu bạn đang sử dụng shell bằng chế độ tương tác trực tiếp, bạn có thể lấy giá trị này bằng việc gõ

    convert image.{png,jpg}

    Will expand to

    convert image.png image.jpg cp /path/to/project/{foo,bar,baz}.sh /newpath

    Will expand to

    cp /path/to/project/foo.sh /path/to/project/bar.sh /path/to/project/baz.sh /newpath

    Globbing techniques can also be combined

    mv {.py,.sh} folder

    Will move all .py and *.sh files

    mkdir foo bar

    This creates files foo/a, foo/b, ... foo/h, bar/a, bar/b, ... bar/h

    touch {foo,bar}/{a..h} touch foo/x bar/y

    Show differences between files in foo and bar

    diff

Chủ Đề