5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

シェルスクリプトのaliasを使った引数の生成(メタプログラミング)

Last updated at Posted at 2024-09-02

はじめに

シェルスクリプトの alias はコマンドに対して別名をつけたり、標準で追加するオプションを定義したりするために、主に(シェルスクリプトではなく)対話シェルで使う機能です。しかしその機能は単語を置き換えるだけという単純な機能であるため、メタプログラミングやシェル言語のハックに利用することができます。これを利用して変数を使わずにコマンドの引数を変更するテクニックを思いついたので紹介します。

コードと説明

# bash の場合にシェルスクリプトでエイリアスを有効にする
[ $BASH_VERSION ] && shopt -s expand_aliases

cmd() { echo "$#" : "$@"; }
alias cmd="cmd "

alias args="a b c"
cmd args # cmd a b c => 3 : a b c

alias args="'a b c'"
cmd args # cmd 'a b c' => 1 : a b c

このコードで珍しいのは、おそらく alias cmd="cmd " の末尾にあるスペースでしょう。本来この機能は後続の単語をエイリアス展開する時に使います。例えば nohup コマンドを使うときなどに使用します。nohup コマンドはコマンドを実行したまま端末をログアウトする時に使うコマンドで以下のような形で使います。

$ nohup backup.sh &

一般的にエイリアスは最初の単語、つまり nohup しかエイリアス展開の対象になりません。もし後続の単語、つまり backup.sh もエイリアス展開の対象にしたい場合は alias nohup="nohup " とエイリアスを定義すれば可能になります。本来はこのように後続の「コマンド」に対してエイリアス展開を行うのですが、結局のところシェルにとってコマンド名と引数に違いはなくどちらも単なる文字列です。別にコマンドでなくとも展開することができます。

エイリアス展開は単なる文字列として展開を行います。したがって次のようなコードは正しく動作します。

alias tr="tr "
alias "%file%"='< "$file"'

file=/etc/hosts
tr %file% a-z A-Z

エイリアスを利用すると変数を使うだけではできないことができてしまうのです。嫌われがちの eval も使用していません。もっともやっていることは eval と大差ありませんが。

さいごに

このようなテクニック(メタプログラミング)は一般的なシェルスクリプトで使うようなものではなく、使い方を間違えるとトラブルの原因になり得ますが、時としてシェルスクリプトの限界を超えるようなことを可能にできたりします。今のところ便利な使い方は思いついていませんが、なにか変わったことができそうだと予感しています。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?