Công dụng:
Khai triển biến như $var nhưng mở rộng thêm các khả năng biến đổi kết quả sau khi khai triển (thay thế, xóa ký tự, thêm ký tự,....).Dùng cho khai triển mảng (array).
Cách dùng:
1,CÁCH CƠ BẢN:
${parameter}
Cũng tương tự như khai triển thông thường $parameter để lấy giá trị của parameter nhưng có thể thêm ký tự đằng sau dấu }. Lệnh sẽ chỉ khai triển paramter trong dấu {} mà không bị ảnh hưởng bởi ký tự bên ngoài.VD:
echo "The plural of $WORD is most likely $WORDs"Ngoài ra, còn có thể khai triển các tham số vị trí trong câu lệnh nếu có hơn 10 vị trí mà không cần dùng lệnh shift để lùi vị trí. ( tham số vị trí chỉ có $1...$9 thôi, source)
# bash sẽ hiểu WORDs là 1 biến khác
echo "The plural of $WORD is most likely ${WORD}s"
#khai triển WORD trước rồi mới thêm s sau kết quả
VD:
set mot hai ba bon nam sau bay tam chin muoi "muoi mot" "muoi hai"Trong một mảng vị trí bắt đầu là 0, ở một vị trí có thể là phần tử rỗng. sử dụng * và @ để lấy giá trị toàn bộ các phần tử.Đọc thêm
echo ${12}Đối với mảng (array):
$array{[2]}
$array{[@]}
VD:
array=(khong mot hai ba bon nam sau bay tam) #tạo mảng.Bonus: Sự khác biệt giữa * và @, cũng giống khi sử dụng tham số vị trí (đây), nếu không có dấu ngoặc kép ("") thì không khác gì nhau, nhưng khi có ngoặc kép thì khi sử dụng * các phần tử được ngăn cách bởi biến IFS, còn @ sẽ là các dấu ngoặc kép và khoảng trắng, các phần sau này sự khác biệt này vẫn có hiệu lực.
echo ${array[2]} #lấy giá trị tham số vị trí 2 của mảng, KQ là "hai"
echo ${array[*]} # lấy giá trị toàn bộ phần tử của mảng.
VD:
echo "${array[@]}"Cái số trong ngoặc vuông (VD số 2 trong array[2]) là số thứ tự các phần tử mảng, do nếu phần tử bị unset thì số này sẽ bị mất và vậy không có thứ tự nữa, nên sau này giữ nguyên tiếng anh, gọi luôn là số index cho nó đỡ phiền.
#kết quả sẽ tương đương
"${array[0]}" "${array[1]}" "${array[2]}" "${array[3]}" "${array[4]}" "${array[5]}" "${array[6]}" "${array[7]}" "${array[8]}"
OLD_IFS="$IFS" #backup biến IFS, 1 thói quen tốt.
IFS=:
echo ${array[*]}
#kết quả tương đương "${array[0]}:${array[1]}:${array[2]}:${array[3]}:${array[4]}:${array[5]}:${array[6]}:${array[7]}:${array[8]}"
2,KHAI TRIỂN GIÁN TIẾP 1 GIÁ TRỊ (INDIRECTION) :
${!parameter}
Dùng để khai triển 1 biến là giá trị của 1 biến khác, chắc chắn không thể nào dùng cú pháp như này được $$aVD:
a=bNếu phối hợp với các cú pháp mở rộng khác thì bash sẽ khai triển gián tiếp trước rồi mới tới cái khác.(khúc này hơi lủng củng vì bí, mọi người vào source đọc cho chắc ăn ("--) ), để nhìn thấy rõ, hãy mở terminal và thử ví dụ này.
b=c
echo ${!a} # kết quả sẽ là "c"
set mot hai ba bon
echo ${!#} # lấy giá trị của tham số vị trí cuối cùng, ở đây là "bon" ($#: số lượng tham số vị trí)
VD:
a=hMột số trường hợp phép khai triển gián tiếp này không hoạt động:
A=d
h=c
echo ${!a^}
# Nếu chỉ ${a^} kết quả sẽ là H ( ^ sẽ in HOA ký tự đầu tiên giá trị lấy được, đọc thêm phía dưới), kết quả ${!a^} sẽ là C.
${!var@}vì tiền tố ! sẽ bị xung đột với các mẫu "name-reference" khi dùng trên các phiên bản tương tự với ksh. (đoạn này chả biết dịch sao nhưng không chơi với ksh nên không quan tâm (--") )
${!var*}
${!var[@]}
${!var[*]}
${#var}
Ngoài ra, còn có thể dùng lệnh eval trong trường hợp khai triển gián tiếp. VD:
a=b
b=c
eval echo \$$a # Kết quả tương đương echo ${!a}
Đối với mảng
Cú pháp gián tiếp này có thể sử dụng cho mảng trên Bash 3 series (chính xác phiên bản nào thì không rõ), nhưng lại không có bản hướng dẫn chính thức nào. Muốn biết thì đọc thêm trong link.(Cái ví dụ trong link khó hiểu quá bác nào hiểu được thì reply, giảng em luôn, xong rồi em bổ sung trong này (--") )
Còn thực nghiệm thì nó như thế này (test trên phiên bản bash version 4.3.11(1)-release, thử nghiệm cá nhân không có trong link source):
- Đối với từng phần tử thì như biến bình thường phía trên.
- Đối với giá trị toàn phần như array[@] và array[*] nó sẽ hiện ra số thứ tự từng phần tử có trong mảng, ứng bao nhiêu phần tử thì có bấy nhiêu số thứ tự, phần tử rỗng vẫn hiện ra số thứ tự nhưng nếu phần tử bị unset sẽ mất số thứ tự.
array=(zero one two three four five) #tạo mảngChưa nghĩ ra công dụng của nó là gì :)).
echo ${!array[@]}
#kết quả 0 1 2 3 4 5
array[3]= #đặt phần tử thứ 3 là phần tử rỗng.
echo ${!array[@]}
#kết quả vẫn là 0 1 2 3 4 5.
unset array[3] #unset phần tử thứ 3.
echo ${!array[@]}
#kết quả 0 1 2 4 5 (mất số 3).
3, CHỈNH SỬA KÝ TỰ HOA/THƯỜNG (CASE MODIFICATION)
${PARAMETER^}
${PARAMETER^^}
${PARAMETER,}
${PARAMETER,,}
${PARAMETER~}
${PARAMETER~~}
Chuyển đổi ký tự HOA/thường của giá trị sau khi khai triển biến theo ý muốn. Do linux có phân biệt ký tự HOA và thường nên cú pháp này khá hữu dụng trong việc đổi tên file hàng loạt, ... Cách nhớ:- Dấu ^ biến đổi ký tự trở thành ký tự HOA.
- Dấu , biến đổi ký tự trở thành ký tự thường.
- Dấu ~ thay đổi trạng thái hiện tại của ký tự, nếu là HOA ➞ thường và nếu là thường ➞ HOA.
- Nếu chỉ 1 dấu thì biến đổi 1 ký tự đầu tiên của giá trị, hai dấu thì biến đổi toàn bộ.
Cái này cũng không quan trọng lắm nhưng vẫn phải ghi ra để tỏ lòng biết ơn. cái cú pháp ~ và ~~kia là không có trong tài liệu chính thức nào cả, là người dùng tự tìm ra. Chân thành cảm ơn 2 thành viên có nick name Bushmills và geirha trên kênh IRC freenode đã tìm ra cái này.var1=saMsungvar2=SamSungecho ${var1^} #kết quả SaMsungecho ${var2,} #kết quả samSungecho ${var1~~} #kết quả SAmSUNG
Một VD đơn giản về chuyển tất cả tên file thành ký tự thường.
for file in *.txt; domv "$file" "${file,,}"done
Đối với mảng
Cú pháp chỉnh sửa này hoàn toàn có thể dùng được cho mảng, dù là từng phần tử hay toàn bộ (@ và *).Đối với từng phần tử: giống với biến thông thường.
Đối với toàn mảng (sử dụng @ và *): nó sẽ tác dụng lên từng giá trị phần tử và hiển thị toàn bộ các giá trị đó lên. VD:
hovaten=(bui thi hoai anh)
echo ${hovaten[2]^} #kết quả Hoai
echo ${hovaten[@]^} #kết quả Bui Thi Hoai Anh
4, HIỂN THỊ CÁC BIẾN CÓ CÙNG TIỀN TỐ
${!PREFIX*}${!PREFIX@}
cú pháp này sẽ hiển thị các tên biến bắt đầu bởi tiền tố prefix (tên biến thôi và không hiển thị giá trị). Sự khác nhau @ và * cũng giống như trên kia.
VD:
echo ${!BASH*}Cú pháp này cũng hiển thị luôn cả tên mảng.
#kết quả BASH BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION
5, GỠ BỎ MỘT PHẦN CHUỖI KÝ TỰ CỦA GIÁ TRỊ BIẾN
${PARAMETER#PATTERN}${PARAMETER##PATTERN}
${PARAMETER%PATTERN}
${PARAMETER%%PATTERN}
Gỡ bỏ một phần chuỗi của giá trị (bỏ phần PATTERN trong giá trị), bắt đầu từ đầu hoặc cuối chuỗi, vậy nên PATTERN phải bắt đầu từ đầu hoặc cuối chuỗi mới có tác dụng. Vì thế cách tạo PATTERN dễ dàng nhất là chọn vài ký tự làm mốc và dùng ký tự * (asterisk) để đại diện cho các ký tự còn lại bắt đầu từ đầu hoặc cuối chuỗi (đọc thêm wildcards để biết nó là gì, rảnh sẽ dịch luôn trong một bài khác). Được dùng rộng rãi khi thao tác với tên file. cách nhớ:
- #: gỡ bỏ chuỗi ký tự từ trái qua.
- %: gỡ bỏ chuỗi ký tự từ phải qua.
- nếu có 2 dấu (## hoặc %%) thì bash sẽ bỏ phần chuổi dài nhất có thể.
string="Be liberal in what you accept, and conservative in what you send"
Cú pháp | Kết quả |
---|---|
${string#* } | |
${string##* } | |
${string% *} | Be liberal in what you accept, and conservative in what you |
${string%% *} | Be |
${string#*in} | |
${string##*in} |
hãy chú ý thứ tự vị trí của dấu cách (space) và dấu * trong 4 ví dụ đầu, 2 ví dụ sau là thêm vào để dễ hiểu hơn. Sau này lật lại xem khỏi bị nhầm lẫn.
Ứng dụng thực tế:
Một số VD thao tác tên file:
lấy tên của file, bỏ qua phần đuôi mở rộngĐây là những cú pháp thao tác với tên file có 1 đuôi mở rộng. Tùy vào cách sử dụng mà có thể điều chỉnh gỡ bỏ nhiều ích cho phù hợp.
${FILENAME%.*}
➡bash_hackers.txt
Lấy phần đuôi mở rộng, bỏ qua tên file
${FILENAME##*.}
➡bash_hackers.txt
lấy đường dẫn đến thư mục
${PATHNAME%/*}
➡/home/bash/bash_hackers.txt
Lấy tên file bỏ qua đường dẫn thư mục
${PATHNAME##*/}
➡/home/bash/bash_hackers.txt
Đối với mảng
Khi sử dụng trên mảng, cú pháp gỡ bỏ này sẽ có hiệu lực lên mỗi phần tử của mảng, khai triển từng phần tử hay toàn bộ mảng đều như nhau, hiệu lực này sẽ ảnh hưởng đối với từng phần tử sau khi khai triển.VD sau sẽ gỡ bỏ "is" khỏi các phần tử có "is" tận cùng bên phải:
array=(this is a text)
echo "${array[@]%is}"
➡ Th a text (this is a text-bị gạch bỏ is)
6, TÌM KIẾM VÀ THAY THẾ
${PARAMETER/PATTERN/STRING}${PARAMETER//PATTERN/STRING}
${PARAMETER/PATTERN}
${PARAMETER//PATTERN}
Tìm kiếm và thay thế mẫu PATTERN bằng chuỗi STRING trong giá trị của biến sau khi khai triển. Nếu không đặt STRING thì cú pháp sẽ xóa PATTERN. 2 kiểu cú pháp chỉ khác nhau số lượng dấu /. Cách nhớ:
một dấu: chỉ thay thế 1 lần.
hai dấu: thay thế toàn bộ.
VD: Thay thế từ "in" bằng từ "by" trong ví dụ dưới:
string="Be liberal in what you accept, and conservative in what you send"
form 1: thay thế 1 từ "in" đầu tiên.
${MYSTRING/in/by}form 2: thay thế toàn bộ từ "in" trong chuỗi
➡Be liberalinby what you accept, and conservative in what you send
${MYSTRING//in/by}Thả neo (Anchoring-dịch ra là thả neo nên để luôn): nếu mẫu xuất hiện nhiều lần trong chuỗi, mà chỉ cần thay thế 1 mẫu thì có thể quyết định thay thế mẫu tận cùng bên trái hoặc bên phải nhờ các ký tự %(percent-sign - dấu phần trăm) và # (hashmark-dấu thăng).VD
➡Be liberalinby what you accept, and conservativeinby what you send
MYSTRING=xxxxxxxxxxNếu để trống phần thay thế sau dấu / thứ 2 của form dùng 2 dấu, sẽ tương đương form dùng 1 dấu /.
echo ${MYSTRING/#x/y}#Kết quả: yxxxxxxxxx
echo ${MYSTRING/%x/y}#Kết quả: xxxxxxxxxy
echo ${MYSTRING//conservative/}
sẽ tương đương
echo ${MYSTRING//conservative}
Đối với mảng:
Đây là cú pháp mở rộng có tác dụng lên tất cả các phần tử của mảng.Cũng giống như cú pháp chuyển đổi HOA/thường trên kia, nó hoạt động trên một giá trị phần tử hoặc từng gía trị trên toàn bộ phần tử mảng (khi sử dụng * hoặc @).VD: thay thế t thành d (khác với source, em thay chữ T trong This thành t cho dễ thấy) :
array=(this is a text)
echo "${array[@]/t/d}"
➡dhis is a dext
echo "${array[@]//t/d}"
➡dhis is a dexd
7, ĐỘ DÀI CỦA CHUỖI.
${#PARAMETER}Dùng cái này nó sẽ cho biết số lượng kí tự trong giá trị của tham số sau khi khai triển.
VD:
MYSTRING="Be liberal in what you accept, and conservative in what you send"Độ dài này được tính bằng số lượng ký tự chứ không phải bytes. Nếu tính bằng bytes thì còn tùy thuộc vào môi trường mà ra kết quả khác nhau (VD multibyte-characters, ký tự chứa nhiều bytes của dạng mã hóa UTF8)
echo ${#MYSTRING}
Kết quả là: 64
Chả có gì nhiều để nói về nó nhỉ ?
Đối với mảng:
Sẽ có khác nhau giữa từng phần tử và toàn bộ mảng:- Đối với một phần tử: cũng như tham số thường trên kia, nó sẽ cho biết số lượng ký tự trong giá trị phần tử đó.
- Đối với toàn bộ mảng: nó sẽ cho biết số lượng phần tử được set của mảng, giá trị phần tử là rỗng vẫn tính nhưng nếu nó bị unset thì thôi.
array=(This is a text)Chú ý: trên kia nói rồi, nhắc lại thôi. Do phần tử bị unset sẽ mất luôn số thứ tự trong mảng nên số index lớn nhất không phải là số lượng phần tử trong mảng. 1 cái mảng với số index lõm tùm lum như 2 6 7 là khả thi đối với bash, Vì thế không thể sử dụng vòng lặp xuyến suốt mảng với số index này.
echo ${#array[1]}
➡2 #từ is có 2 ký tự.
echo ${#array[@]}
➡4 #mảng có 4 phần tử được set.
array[1]="" #đặt phần tử 1 là rỗng.
echo ${#array[@]}
➡4 #vẫn là 4
unset array[1] #unset phần tử 1
echo ${#array[@]}
➡3
8, KHAI TRIỂN 1 PHẦN CHUỖI TRONG GIÁ TRỊ (SUBSTRING EXPANSION).
Hồi nãy là cách gỡ bỏ 1 phần chuỗi, còn đây là giữ lấy 1 phần chuỗi của giá trị.${PARAMETER:OFFSET}
${PARAMETER:OFFSET:LENGTH}
Cú pháp này hoạt động như sau: chọn 1 điểm mốc (OFFSET) và độ dài (LENGHT) của chuỗi con. Nó sẽ khai triển từ điểm mốc đó (giữ luôn điểm mốc lại) đến khi đủ số lượng ký tự độ dài. Nếu để trống độ dài, nó sẽ khai triển đến hết giá trị.
OFFSET và LENGTH có thể là bất kỳ biểu thức đại số nào ở đây link .
CHÚ Ý: OFFSET BẮT ĐẦU TỪ 0 CHỨ KHÔNG PHẢI 1, KÝ TỰ Ở VỊ TRÍ OFFSET CHỈ RA ĐƯỢC GIỮ LẠI. (theo đúng source thì là vậy, nhưng nếu tính offset bắt đầu từ số 1 thì offset sẽ trở thành số lượng ký tự bị mất, hiểu theo cách nào tùy mỗi người, nhưng tí nữa em sẽ phụ chú thêm 1 cái bảng tóm tắt hiểu theo kiểu này cho dễ nhớ, ai không thích cứ hiểu theo cách của source, còn nếu cách hiểu của source là bắt buộc thì hãy cmt phía dưới để em xóa bỏ)
Còn đây là phần dịch của source với ví dụ
MYSTRING="Be liberal in what you accept, and conservative in what you send"
TH1: Chỉ sử dụng duy nhất offset:
Trường hợp này chỉ sử dụng số offset, bỏ qua số lenght, chú ý offset được tính từ 0.
echo ${MYSTRING:34}
Be liberal in what you accept, and conservative in what you send (gạch 34 ký tự đầu)
TH2: Sử dụng cả offset và lenght:
Trường hợp này có thêm lenght, chỉ ra số lượng ký tự được giữ lại.
echo ${MYSTRING:34:13}
Be liberal in what you accept, and conservative in what you send (gạch 34 ký tự đầu, giữ lại 13 ký tự tiếp theo, gạch bỏ phần còn lại)
TH3: sử dụng offset là số âm:
Nếu offset là số âm, thì sẽ được đếm từ phải qua. ký tự offset chỉ ra và phần bên phải nó sẽ được giữ lại, offset lần này đếm từ -1 (rồi chữa ? :))) còn lenght vẫn là số lượng ký tự được giữ lại đếm từ mốc offset qua phải như cũ.
Chú ý: giữa dấu :(colon) và dấu -(negative) phải có khoảng trắng, hoặc đặt dấu âm vào ngoặc (). Để phân biệt với "cú pháp khai triển giá trị mặc định" ở dưới sẽ trình bày.
${MYSTRING: -10:5}
${MYSTRING:(-10):5}
TH4: sử dụng lenght là số âm:
Nếu lenght là số âm, cũng giống như offset là số âm, sẽ được đếm tứ phải qua trái, chỉ khác nó là số lượng ký tự bị bỏ đi. việc khai triển sẽ từ vị trí offset đến phần còn lại.
echo "${MYSTRING:11:-17}"
Be liberal in what you accept, and conservative in what you send (gạch bỏ 11 ký tự đầu và 17 ký tự cuối)
Cái này có thể dùng từ Bash 4.2-alpha,xem thêm những thay đổi của bash.(link http://wiki.bash-hackers.org/scripting/bashchanges)
Xong phần dịch của source, bây giờ sẽ là tổng hợp cho dễ nhớ (cứ dùng nhiều tự khắc nhớ thôi):
hãy quan niệm, offset và lenght đều là số đếm ký tự (không giống suorce, vị trí rồi số 0 này nọ) ta có cái bảng tóm tắt này, các bác hãy kiểm nghiệm xem đúng không ?
Số Dương | Số Âm | |
---|---|---|
offset | ký tự mất, từ trái | ký tự còn, từ phải |
lenght | ký tự còn, từ trái | ký tự mất, từ phải |
Đối với mảng:
Được chia làm 2 trường hợp:- Đối với một phần tử: thì như trên kia, không khác biến thường.
- Đối với toàn mảng (dùng ký tự @ và *): các con số sẽ đại diện cho phần tử, chứ không còn đại diện ký tự nữa, phần được khai triển trong toàn mảng được xác định bởi 2 con số: số đầu tiên chính là số index chỉ vị trí phần tử bắt đầu được giữ lại (số index bắt đầu từ số 0) và số tiếp theo là số lượng phần tử được khai triển.
VD:
array=(This is a text)
echo ${array[0]:2:2}
⇒ is (từ "is" trong "This", của phần tử 0)
echo ${array[@]:1:2}
⇒ is a (bắt đầu giữ lại từ phần tử 1 và giữ lại 2 phần tử là 1 và 2)
9, KHAI TRIỂN MỘT GIÁ TRỊ MẶC ĐỊNH
${PARAMETER:-WORD}${PARAMETER-WORD}
Ở form 1, nếu PARAMETER chưa được set (unset) hoặc là biến rỗng (null) thì sẽ cho ra kết quả mặc định là WORD, nếu set giá trị rồi thì sẽ khai triển PARAMETER như bình thường (như thế này ${PARAMETER}). Khác biệt giữa 2 form là dấu :(colon), nếu KHÔNG có dấu :, WORD chỉ được khai triển khi PARAMETER unset, còn biến rỗng (null) vẫn khai triển ra giá trị rỗng như bình thường.
VD:
echo "Your home directory is: ${HOME:-/home/$USER}."Nếu user chưa có home folder thì vẫn hiện đường dẫn đến dù chưa có.
echo "${HOME:-/home/$USER} will be used to store your personal data."
#!/bin/bashNếu không nhập GENDER thì sẽ hiện ra "Your gender is a secret". Chú ý: cú pháp này chỉ khai triển ra WORD trong lần sử dụng chứ không gán giá trị WORD cho biến PARAMETER, biến PARAMETER vẫn sẽ có giá trị là unset (hoặc null).
read -p "Enter your gender (just press ENTER to not tell us): " GENDER
echo "Your gender is ${GENDER:-a secret}."
Đối với mảng:
Cũng giống những cái cú pháp trên, sẽ có sự khác nhau khi áp dụng cú pháp này trên mỗi phần tử (chỉ định số index) và trên toàn bộ phần tử (dùng * và @):- Đối với 1 phần tử lẻ được chỉ định số index rõ ràng, cũng giống như cú pháp này với biến bình thường, nếu phần tử unset hoặc null (null có được khai triển hay không thì tùy vào :- hay -, giống trên kia luôn) thì sẽ khai triển đoạn chuỗi mặc định WORD.
- Đối với toàn bộ mảng khi dùng * và @, chuỗi mặc định WORD sẽ được khai triển nếu toàn bộ phần tử trong mảng là unset (hoặc null nếu dùng :- trong cú pháp), và sẽ khai triển toàn bộ mảng như bình thường nếu có phần tử được set (hoặc null nếu dùng - trong cú pháp pháp). Tức là không khác trên kia chỉ là mở rộng ra toàn bộ mảng thôi.
VD:
####Thôi cũng cố làm 1 cái bảng tóm tắt cho dễ nhớ, sau này xem lại không cần nhìn cái wall of text trên kia.
# Example cases for unset/empty arrays and nullstring elements
####
### CASE 1: Unset array (no array)
# make sure we have no array at all
unset array
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 2: Set but empty array (no elements)
# declare an empty array
array=()
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 3: An array with only one element, a nullstring
array=("")
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
### CASE 4: An array with only two elements, a nullstring and a normal word
array=("" word)
echo ${array[@]:-This array is NULL or unset}
echo ${array[@]-This array is NULL or unset}
unset | null | |
---|---|---|
:- | WORD | WORD |
- | WORD | $PARAMETER |
10, KHAI TRIỂN VÀ GÁN 1 GIÁ TRỊ MẶC ĐỊNH CHO BIẾN:
${PARAMETER:=WORD}${PARAMETER=WORD}
Cũng giống như cú pháp khai triển giá trị mặc định cho biến trên kia, nhưng không chỉ khai triển khi biến unset (hoặc null), cú pháp này sẽ đặt luôn giá trị mặc định này cho biến. Dấu :(colon) cũng tạo ra sự khác biệt khi biến là null giữa 2 form (giống cú pháp kia luôn).
VD:
echo "Your home directory is: ${HOME:=/home/$USER}."sau khi chạy VD trên sẽ thấy biến HOME đã được set và gán giá trị mặc định.
echo "$HOME will be used to store your personal data."
hãy tạo 1 script với thí dụ bên dưới:
#!/bin/bash
read -p "Enter your gender (just press ENTER to not tell us): " GENDER
echo "Your gender is ${GENDER:=a secret}."
echo "Ah, in case you forgot, your gender is really: $GENDER"
Đối với mảng:
Sẽ có khác biệt với cú pháp này, đối với từng phần tử của mảng sẽ không có gì khác khi với biến thông thường. Nhưng, đối với toàn bộ mảng (dùng @ hoặc *) thì cúp pháp này sẽ KHÔNG HOẠT ĐỘNG, bởi vì không thể gán giá trị mặc định cho chúng. Chạy thử thì báo lỗi như này "-bash: i[@]: bad array subscript".11, KHAI TRIỂN MỘT GIÁ TRỊ THAY THẾ.
${PARAMETER:+WORD}${PARAMETER+WORD}
Ngược lại với cú pháp giá trị mặc định trên kia, nó sẽ khai triển ra giá trị thay thế WORD nếu như biến PARAMETER có giá trị. Còn nếu là unset hoặc null thì nó sẽ không khai triển ra gì cả.VD:
echo "The Java application was installed and can be started.${JAVAPATH:+ NOTE: JAVAPATH seems to be set}"ví dụ trên sẽ đưa ra 1 cảnh báo nếu biến JAVAPATH được set (vì nó có thể ảnh hưởng tới quá trình khởi động của một ứng dụng giả định nào đó)
Trong các ví dụ giả định tiếp theo, sẽ xem tình trạng của các cờ (lập trình nhiều thì chắc các bác biết cờ là cái gì rồi), và sẽ in ra 1 dòng cảnh báo nếu cờ được set.
#!/bin/bashDấu :(colon) cũng tạo ra sự khác nhau giữa 2 form khi biến là rỗng, khi thiếu dấu : (chính là form 2) , biến là null thì cú pháp sẽ khai triển ký tự thay thế.
read -p "If you want to use special flags, enter them now: " SPECIAL_FLAGS
echo "The installation of the application is finished${SPECIAL_FLAGS:+ (NOTE: there are special flags set: $SPECIAL_FLAGS)}."
chạy script dưới để kiểm tra:
# test that with the three stages:
# unset foo
# foo=""
# foo="something"
if [[ ${foo+isset} = isset ]]; then
echo "foo is set..."
else
echo "foo is not set..."
fi
Đối với mảng:
Như hầu hết cú pháp:- Đối với MỘT phần tử của mảng, cú pháp này hoạt động bình thương như đối với biến thông thường.
- Đối với toàn bộ mảng (dùng @ và *), cú pháp sẽ cho ra chuỗi thay thế nếu trong mảng có ít nhất một phần tử chứa giá trị hoặc null (null có được khai triển hay không thì tùy vào :+ hay + nhé).
12, CÚ PHÁP BÁO LỖI NẾU NULL HOẶC UNSET
${PARAMETER:?WORD}${PARAMETER?WORD}
Nếu biến PARAMETER có giá trị hoặc đã được set, cú pháp này sẽ khai triển như thông thường. Nhưng nếu PARAMETER unset hoặc null, thì WORD sẽ được thêm vào phần thông báo lỗi của bash.
$ echo "The unset parameter is: ${p_unset?not set}"Vậy tại sao không dùng luôn cú pháp khai triển giá trị mặc định trên kia ? khác biệt ở chỗ, nếu khai triển ra thông báo lỗi này, giá trị biến báo trạng thái exit $? của lệnh vừa thực thi sẽ khác 0. ( biến ? là cái gì thì xem ở đây link). Cụ thể:
bash: p_unset: not set
- Đối với shell có tương tác (cái bảng đen các bác gõ vào trên 1 cái tty): giá trị biến báo trạng thái exit $? sẽ khác 0.
- Đối với shell không có tương tác ( là các bác viết nó thành script rồi chạy): mã exit khi kết thúc script sẽ khác 0.
Và dấu :(colon) cũng có tác dụng tương tự khi biến là null.
- có dấu : trong cú pháp (:?): biến null cũng khai triển ra báo lỗi.
- không có dấu : trong cú pháp (?): biến null được khai triển bình thường.
PARAMETER EXPANSION tới đây là hết nước hết cái rồi, phần sau là Bugs and Portability considerations. Cảm thấy cần cứ đọc thêm cho biết.
p/s: sai chỗ nào góp ý chỉnh sửa dùm, đừng đọc xong xách đít ra đi. Do đết biết HTML nên trình bày không bằng cái source mọi người thông cảm, mà mục đích chính để ghi nhớ vàgiúp mọi người chỉ là phụ nên chả quan trọng mấy. 😉😊
Vừa mua 1 con card màn hình, kế tiếp sẽ dịch cái tut hướng dẫn cài driver NVIDIA.