Vietnamese Developers’ Blog

Lấy xâu con trong shell script

Posted in Unix/Linux/BSD by kiennguyen on May 19, 2008

Hôm trước nhân lúc nhàn rỗi mình có giúp một “đồng nghiệp” viết một script nhỏ bằng ZShell phục vụ cho việc testing. Do công việc hàng ngày chỉ là viết các script đơn giản nên mình đã khá lúng túng trước yêu cầu phải lấy ra được một xâu con (substring) từ một xâu khác. Lên Google search thì thấy cũng có khá nhiều người gặp khó khăn trước vấn đề này và hóa ra xử lí xâu trong shell cũng là một vấn đề khá thú vị. Bài viết này tổng kết những phương pháp để lấy substring trong shell mà tác giả lượm lặt trên mạng. Chú ý rằng những phương pháp này có thể không áp dụng được với một số loại shell nhất định.

Những kĩ thuật dưới đây được áp dụng để giải quyết bài toán cụ thể là lấy ra xâu “substring” từ xâu “this is a substring test”. Bài toán này có ý nghĩa trong trường hợp substring là một biến có thể nhận nhiều giá trị khác nhau.

1- Sử dụng cú pháp substring=${string:starting_position:length}

string=”this is a substring test”
substring=${string:10:9}
echo $substring

substring

Chú ý rằng vị trí đầu tiên trong một xâu là 0. Nhược điểm của cách này là chỉ áp dụng khi xâu con cần lấy ra có độ dài cố định. Hơn nữa cách này không áp dụng được cho zshell, một loại shell được dùng phổ biến trên các hệ thống UNIX.

2- Sử dụng lệnh cut
Lệnh cut dùng để lấy ra một số kí tự trong một xâu. Dùng man cut để xem chi tiết về lệnh này. Trong bài toán cụ thể của chúng ta, trong xâu string thì xâu con “substring” bắt đầu từ vị trí 11 và kết thúc ở vị trí thứ 19. Bởi vậy có thể dùng lệnh sau đây để cắt ra “substring”

string=”this is a substring test”
echo $string | cut –c11-19

substring

Nhược điểm của cách làm này là chỉ áp dụng với xâu con có độ dài cố định. Chúng ta có thể sử dụng lệnh cut với các tham số sau đây đề khắc phục nhược điểm đó

string=”this is a substring test”
echo $string | cut –d’ ‘ –f4

substring

Lệnh trên lấy ra trường thứ 4 (f = field) của xâu string, mỗi trường cách nhau bởi kí tự space (d=delimeter).

3- Sử dụng các toán tử #, ##, % và %%

Toán tử # nghĩa là xóa bắt đầu từ bên trái xâu đầu tiên thỏa mãn mẫu (pattern) theo sau dấu #

string=”this is a substring test”

# mẫu “* “ sau dấu #, xóa từ bên trái xâu đầu tiên có dạng một xâu hay một kí tự bất kì
#theo sau bởi kí tự space, tức là xâu “this “
#(chú ý “*” đại diện cho một xâu hay kí tự bất kí)
substring=${string#* }

echo $substring

is a substring test

Toán tử ## nghĩa là xóa bắt đầu từ bên trái xâu cuối cùng thỏa mãn mẫu (pattern) theo sau dấu ##

string=”this is a substring test”

# mẫu “* “ sau dấu ##, xóa từ bên trái xâu cuối cùng có dạng một xâu hay kí tự bất kì
#theo sau bởi kí tự space, tức là xâu “this is a substring “
substring=${string##* }

echo $substring

test

Toán tử % nghĩa là xóa từ bên phải xâu đầu tiên thỏa mãn mẫu (pattern) theo sau dấu %.

string=”this is a substring test”

# mẫu “ *” sau dấu %, xóa từ bên phải xâu đầu tiên có dạng kí tự space
#theo sau bởi một xâu hay kí tự bất kí, tức là xâu “ test”.
substring=${string% *}

echo $substring

this is a substring

Toán tử %% nghĩa là xóa từ bên phải xâu đầu tiên thỏa mãn mấu (pattern) theo sau dấu %%.

string=”this is a substring test”

#mẫu “ *” sau dấu %%, xóa từ bên phải xâu cuối cùng có dạng kí tự space
#theo sau bởi một xâu hay kí tự bất kì, tức là xâu “ is a substring  test”
substring=${string%% *}

echo $substring

this

Trở lại bài toán ban đầu, để lấy ra xâu “substring” chúng ta cần xóa đi hai xâu “this is a “ và “ test”. Việc xóa đi xâu “ test” đã được nói đến ở trên:

substring=${string% *}

Có nhiều cách để xóa nốt xâu “this is a “. Xâu này có đặc điểm là xâu đầu tiên có dạng một xâu bất kì theo sau bởi kí tự ‘a’ theo sau bởi kí tự space. Bởi vậy có thể viết

substring=${substring#*a }
echo $substring

substring

Đơn giản hơn, đó chính là xâu có dạng “this is a “!!!. Bởi vậy chúng ta có cách thứ hai sau đây

substring=${substring#this is a }
echo $substring

substring

Ngoài những cách nói trên thì sed và awk cũng là những công cụ rất mạnh để xử lí xâu. awk có hẳn một hàm substr để lấy ra các xâu con từ một xâu. Tác giả đã có một bài viết về sed và hi vọng sẽ sớm có một bài giới thiệu awk trong tương lai gần.

Một trang web thú vị tổng hợp các cú pháp của lập trình bash shell là: http://www.arachnoid.com/linux/shell_programming.html
Cái thú vị nhất ở trang này là lời khẳng định sau đây: “I want to say at the outset that shell programming is an art, not a science. That means there is always some other way to do the same thing.

Tagged with: , ,

One Response

Subscribe to comments with RSS.

  1. Vân Anh said, on May 20, 2008 at 11:49 am

    Trong zshell chúng ta có thể sử dụng cú pháp $string[ start_position, end_position ] để lấy ra xâu con bắt đầu từ vị trí start_position và kết thúc ở end_position. Ví dụ:
    string=”this is a substring test”
    echo $string[ 11, 19 ]

    substring


Leave a Reply