Help us understand the problem. What is going on with this article?

bashの関数を削除するシェルスクリプトをVimで無理やり書いた→普通にsedで書けた

More than 3 years have passed since last update.

動機

bashのエイリアスや関数を簡単に削除したい。

あるいはShellScript - bashの各種コマンドを編集するシェルスクリプト - Qiitaの拡張。

複数行の削除がめどい

以下のようなエイリアス定義ファイルがあるとします。

alias-init.bash
unalias -a # すべてのエイリアスを削除
alias mi='open -a mi'
alias ft='open -a FoldingText'
alias marked='open -a "Marked 2"'
alias st='open -a "Sublime Text"'
# 以下略

あるエイリアスを削除するスクリプトは、以下のように簡単に書けます。

# Mac
# bash_alias=~/.bash/conf/alias-init.bash

# Macビルトインのsed(BSD版)
deletealias1 () {
  sed -i ''  "/^alias $1=/d" "$bash_alias"
}
# GNU-sed
deletealias2 () {
  gsed -i "/^alias $1=/d" "$bash_alias"
}

しかし、以下のような関数定義ファイルから特定の関数を削除するのは、複数行に渡ることから大変厄介です。吐きそうになります。

function-init.bash
for f in $(declare -F | cut -d' ' -f3); do unset -f "$f"; done # すべての関数を削除
afunc () {
  pwd
}
bfunc () {
  echo "hoge"
}

Vimで複数行を削除する

しかし、Vimでやるなら簡単です。VでVisual lineに入ってから/^}すれば、ひとつの関数を簡単に選択できます。

そこで、以下のような関数にしてみました。

# bash_function=~/.bash/conf/function-init.bash
# 与えられた関数名を検索し、}で始まる行までを選択して削除、保存して終了
deletefunction () {
  vim +"/^$1 () {" +"normal V" +"/^}" +"normal d" +"wq" "$bash_function"
}

一瞬Vimの画面が開くのが気持ち悪いですが、選択したところで止めたりすると確認できてむしろ良いかも。

削除の反映

普通.bashrcなどの初期化ファイルの更新を反映させる際には、source ~/.bashrcなどとします。エイリアスや関数を追加した場合はsource "$bash_function"で問題ないのですが、削除(あるいは関数名変更)した場合はこれだと反映されません。

そもそもsourceコマンドの仕組みは、引数に与えられたファイル内のスクリプトを実行しているにすぎません。関数定義コマンドを再度実行しても、カレントシェルで定義された関数が削除されることはないわけです。

カレントシェルの関数(または変数)定義を削除するには、unsetコマンドを利用します。同様に、エイリアスの削除にはunaliasコマンドを利用します。

$ alias hoge=pwd
$ hoge
/Users/catfist/Documents
$ unalias hoge
$ hoge
bash: hoge: command not found

$ cd ~/Documents
$ fpwd () { pwd; }
$ func
/Users/catfist/Documents
$ unset func
$ func
bash: func: command not found

# 関数の一覧を出力
$ declare -F
declare -f afunc
declare -f bfunc
# 以下略

これを定義ファイルの先頭に加えることで、定義ファイルから削除された関数等が、sourceした際にカレントシェルからも削除されます。(コメント参照)

あるいは、時間がかかりますが、いっそexec /bin/bashで新規シェルを起動してしまう方法もあります。この場合、変更された定義ファイルを元に、エイリアスや関数を初期化することができます。

bashのエイリアス/関数/プログラムを編集するシェル関数

現時点では以下の通り。長いのでリンクにします。

https://gist.github.com/e1c020a4e12ed5dce71d

sedでも書けた

大したことなかった。

# Mac(BSD sed)
deletefunction () {
  sed -i '' "/^$1 () {/,/^}/d" "$bash_function"
}
  • ""内の/~/がパターン指定
  • ^$1 () {から^}までを読み込み(開始と終了を,区切り)
  • dで読み込んだ部分を除外
  • -iで上書き。バックアップファイルの拡張子を''(空)にしてバックアップしない

関連

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away