Xử lý chuỗi trong linux

Trim leading and trailing white-space from string

Function này hoạt động bằng cách tìm tất các các khoản trắng và xoá nó khỏi đầu và cuối chuỗi.

Dấu “:” được sử dụng như 1 biến tạm thời.

trim_string[]
{
    # Usage: trim_string "   example   string    "
    : "${1#"${1%%[![:space:]]*}"}"
    : "${_%"${_##*[![:space:]]}"}"
    printf '%s\n' "$_"
}

Giải thích:

  • Đầu tiên, ta sẽ phân tích dòng đầu tiên của function trên: : “${1#”${1%%[![:space:]]*}”}”
# đoạn này có tác dụng loại bỏ chuỗi dài nhất không phải khoản trống từ bên phải chuỗi
# kết quả ta sẽ được khoản trắng ở đầu chuỗi cần cắt.

"${1%%[![:space:]]*}"

vd:  string =     "    Hello,  World    "
                       |________________|
                             %%

# tiếp theo ta thực hiện loại bỏ chuỗi vừa thu được ở trên
# ra khỏi chuỗi cần cắt từ bên trái chuỗi.

"${1#"${1%%[![:space:]]*}"}"

vd:  string =     "    Hello,  World    “
                  |___|
                    #

Kết quả ta được chuỗi “Hello, World ”

  • Tiếp theo ta sẽ phân tích dòng tiếp theo:   “${_%”${_##*[![:space:]]}”}”
# đoạn này có tác dụng lấy phần khoản trắng phía sau của chuỗi

"${_##*[![:space:]]}"

vd:  string =     "Hello,  World    "
                  |____________|
                        ##

# tiếp đến sẽ cắt đoạn string mới lấy được phía trên ra khỏi chuỗi được xét.

"${_%"${_##*[![:space:]]}"}"

vd:  string =     "Hello,  World    “
                                |__|
                                 %

Kết quả ta sẽ được chuỗi “Hello, World”

  • Tổng hợp, ta có sử dụng dòng đầu tiên để xoá đi khoản trắng phía đầu chuỗi rồi gán vào biến “:” tiếp đó ta cắt tiếp khoản trắng phía sau chuỗi vừa nhận được. Cuối cùng ta nhận được chuỗi đã loại bỏ hết khoản trắng trước và sau chuỗi.

Trim all white-space from string and truncate spaces

# shellcheck disable=SC2086,SC2048
trim_all[] {
    # Usage: trim_all "   example   string    "
    set -f
    set -- $*
    printf '%s\n' "$*"
    set +f
}

Đầu tiên ta sẽ tìm hiểu về “set” , “set” được sử dụng để thiết lập và sửa đổi các biến nội bộ của shell. Trong trường hợp của hàm ở trên, “set” được sử dụng để thiết lâp gía trị cho các biến vị trí.

Ví dụ: ta có file set.sh có nội dung:

var="Welcome to thegeekstuff"
set -- $var
echo "\$1=" $1
echo "\$2=" $2
echo "\$3=" $3

khi thực hiện ./set.sh ta sẽ được kết quả in ra màn hình như sau:

$1=Welcome
$2=to
$3=thegeekstuff

Tương tự với hàm trim_all[] trên, khi ta chạy:

trim_all "    Hello,    World    "

sau khi thực hiện set — $* ta sẽ có được giá trị $1 = “Hello,”, $2 = ” World”, như ta biết biến $* sẽ chứa tất cả các tham số đầu vào của script, có nghĩa là biến $* sẽ bao gồm các biến $1, $2. Vì vậy khi ta thực hiện printf ‘%s\n’ “$*” bash sẽ thực hiện in ra màn hình giống như printf ‘%s\n’ “$1 $2”. Vì vậy ta được kết quả là “Hello, World”.

Tương tự với:

name="   John   Black  is     my    name.    "
trim_all "$name"

ta sẽ có được $1=”John”, $2=”Black”, $3=”is”, $4=”my”, $5=”name.”

cuối cùng ta sẽ có được kết quả là:   “John Black is my name.”

Ngoài ra trong hàm trên ta cũng thấy được set -f là set và option -f, option này có tác dụng là vô hiệu hóa các phần mở rộng filename.

Use regex on a string

Kết quả của việc so trùng bash’s regex có thể được sử dụng để thay thế “sed” trong phần lớn các trường hợp ứng dụng.

Tuy nhiên, chức năng này của Bash là một trong số ít chức năng phụ thuộc vào nền tảng hệ điều hành. Bash sẽ sử dụng bất cứ trình xử lý regex [regex engine] nào được cài đặt trên hệ thống của người dùng.

Ví dụ1: ta có 1 đoạn hội thoại

string="hue, Hex, Rgb, Hsl. 0, #ff0000, rgb[255, 0, 0], hsl[0, 100%, 50%]. 15, #ff4000, rgb[255, 64, 0], hsl[15, 100%, 50%]. 30, #ff8000, rgb[255, 128, 0], hsl[30, 100%, ..."

# ta muốn lấy ra tất cả các mã màu theo dạng "#......" ta dùng hàm sau

regex[] {
    # Usage: regex "string" "regex"
    for word in $1
    do
        [[ $word =~ $2 ]]
        if [[ ${BASH_REMATCH[1]} ]]
        then
            printf '%s\n' "${BASH_REMATCH[1]}"
        fi
    done
}

regex "$string" '[#[[a-fA-F0-9]{6}|[a-fA-F0-9]{3}]]'

ta sẽ được kết quả:

#ff0000
#ff4000
#ff8000

Ví dụ 2: ta có 1 chuỗi string, ta muốn kiểm tra nó có phải là 1 email hay không

string="[email protected]"
string2="[email protected]"

regex[] {
    # Usage: regex "string" "regex"
    [[ $1 =~ $2 ]] && printf '%s\n' "${BASH_REMATCH[1]}"
}

khi ta chạy lệnh:

regex "$string" '^[[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,4}]$'

ta sẽ được kết quả: [email protected]

regex "$string2" '^[[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\.[A-Za-z]{2,4}]$'

ta sẽ được kết quả rỗng.

Tích hợp vào script ta có hàm kiểm tra màu như sau:

is_hex_color[] {
    if [[ $1 =~ ^[#?[[a-fA-F0-9]{6}|[a-fA-F0-9]{3}]]$ ]]; then
        printf '%s\n' "${BASH_REMATCH[1]}"
    else
        printf '%s\n' "error: $1 is an invalid color."
        return 1
    fi
}

color="#444444"
is_hex_color "$color" || color="#FFFFFF"

# kết quả: #444444

color="#444444134235"
is_hex_color "$color" || color="#FFFFFF"

# kết quả: error: #444444134235 is an invalid color. //echo $color    =>     #FFFFFF

Split a string on a delimiter

Lưu ý: hàm dưới đây yêu cầu phiên bản bash từ 4. trở lên

split[] {
   # Usage: split "string" "delimiter"
   IFS=$'\n' read -d "" -ra arr 

Chủ Đề