閑話休題、変数展開との組み合わせで面白いことできるんじゃないの的なお話。
変数展開
普通の変数展開については既に知ってる前提で。で、配列変数においても変数展開が可能です。まずは特定要素の変数展開をば。
$ foo=("bar" "baz")と期待通りの動作をしてくれます。デフォルト値の設定も同様に
$ echo "${foo[0]:-qux}"
bar
$ echo "${foo[2]:-qux}"
qux
$ foo=("bar" "baz")と期待通りの動作ですね。
$ : "${foo[2]:=qux}"
$ declaare -p foo
declare -a foo='([0]="bar" [1]="baz" [2]="qux")'
$ : "${foo[1]:=quux}"
$ declaare -p foo
declare -a foo='([0]="bar" [1]="baz" [2]="qux")'
その他にも ${var:?word} ${var:+word} も同様に想像通りの動作をしてくれます。
応用編
特定要素ではなくインデックスに @ を指定して変数展開をすると、文字列処理が一気に出来ます。Python ユーザーあたりにはウケがよさそうな
$ foo=("bar" "baz")
$ qux=("${foo[@]//a/A}")
$ declare -p qux
declare -a qux='([0]="bAr" [1]="bAz")'
みたいなことができてしまいます。これは配列の各々の要素において "a" を "A" に置換しています。このように for ループ無しで一気に文字列を処理できます。
これって Python での
>>> foo = ['bar', 'baz']
>>> qux = [s.replace('a', 'A') for s in foo]
>>> qux
['bAr', 'bAz']
にちょっと似てると思いません?でもってかなり短く書けます。
当然、変数展開の範囲内でしかできませんが、もうちょっとスクリプトっぽくすると
$ backups=(*~)
$ original_files=("${backups[@]:0:-1}")
$ for f in "${original_files}"; do
> if [[ -f "${f}" ]]; then
> rm "${f}"~
> fi
> done
みたいな、Pythonでいえば
>>> backups = glob.glob('*~')
>>> original_files = [f[0:-1] for f in backups]
>>> for f in original_files:
... if os.path.exists(f):
... os.unlink(f + '~')
...
感じのことができます(ただし Bash スクリプトの例では、ファイル名に空白が含まれていると期待した動作をしません)。ちゃんと説明すると、
- *~ でファイル名が ~ で終わるファイルのリストを取得
- それらのファイル名から末尾の ~ を削除
- ~ 無しのファイルが存在する場合は
- ~ 付きのファイルを削除
という処理をしています。
他の ${var##word}, ${var%%word} といった文字列展開と組み合わせると、さらにいろんな事ができるのですが、もう眠いので今日はこのへんで。
0 件のコメント:
コメントを投稿