節錄翻譯:All about {Curly Braces} in Bash (Bash 裡所有關於大括號的事)

Source:




根據原文,{} (Curly Braces) 主要有三種功能:

  1. Array Builder
  2. Parameter Expansion
  3. Output Grouping



A) Array Builder

製作 Sequences

1
2
3
echo {0..10}
    
    0 1 2 3 4 5 6 7 8 9 10

或是倒過來:

1
2
3
echo {10..0}
    
    10 9 8 7 6 5 4 3 2 1 0

間隔也可以改變:

1
2
3
echo {10..0..2}
    
    10 8 6 4 2 0

此外也不一定只能使用數字:

1
2
3
echo {a..z}
    
    a b c d e f g h i j k l m n o p q r s t u v w x y z

當然,字母間隔也可以改變:

1
2
3
echo {z..a..2}
    
    z x v t r p n l j h f d b

(字母間隔 zsh 看起來不支援)


更可以把兩組字母放在一起

1
2
3
4
5
6
7
echo {a..z}{a..z}
    
    aa ab ac ad ae af ag ah ai aj ak
    
    ...
    
    zo zp zq zr zs zt zu zv zw zx zy zz

Array 取值

  • Array 用小括號製作

  • 跟 Python 一樣,取值從 0 開始,所以 [3] 其實是第 4

1
2
3
4
month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
echo ${month[3]} 
    
    Apr

結合前面的例子,快速製作 Array:

1
2
3
letter_combos=({a..z}{a..z})
echo ${letter_combos[5]}
    af

甚至可以這樣製作轉換二進位的 array:

1
2
3
4
5
6
    # 這個挺酷
    
dec2bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
echo ${dec2bin[25]}
    
    00011001

當然平常轉換二進位應該用這種方式



B) Parameter Expansion

除了上面提到的取值外,curly brace 還能做更多:

Parameter expansion involves what it says on the box: it takes the variable or expression within the braces and expands it to whatever it represents.

亦即,它可以把原有的變數用你想要的方式呈現出來。

事實上,前面 Array 看起來是取值,細節上也是將原有的 array 變數依照 index 轉成字串,也就是

1
2
3
echo "Apr"
    
    Apr

回到正題:

  • % :從字串的最後切割匹配的字串,例如
1
2
3
4
a="Too Longggg"
echo ${a%ggg}
    
    Too Long

舉個相對實用的例子,假設想要轉換圖片檔:

1
convert image.jpg image.png

用前面的技巧,可以改寫成:

1
2
i=image.jpg
convert $i ${$i%jpg}png

加上 for loop 就更強大了

1
for i in *.jpg; do convert $i ${i%jpg}png; done

如果不想從字串的最後切,改從最前面開始呢?

  • # :從字串的開始切割匹配的字串,例如
1
2
3
4
5
a="Hello World!"
    
echo Goodbye${a#Hello}
    
    Goodbye World!

parameter expansion 還有更多細節,但必須要配合 script 才能發揮效果,之後會回頭談。



C) Output Grouping

如果有好幾組指令要執行,然後統一 output 到某個檔案,就需要用 curly brace 達成。

例如:

1
echo "I found all these PNGs:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls > PNGs.txt

如果想將所有結果輸出到 PNGs.txt,會發現這樣下只有會 ls 的結果。

那怎麼辦?

用 curly brace 包起來:

1
{ echo "I found all these PNGs:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls; } > PNGs.txt

需要特別注意:curly brace 內需要各留一個空白,bash 才能正確解析。


主題 StackJimmy 設計