ループ内で変数展開を伴うコマンドを生成する

ループ内で変数展開を伴うコマンドを生成する

特定のディレクトリで作業するときにローカルエイリアスを作成したい。たとえば、次のファイルを次のようにしたい。local_alias

alias foo='bar'

作業終了後にこれらのエイリアスを削除するクリーンアップ スクリプトを書きたいと思いました。次のようなものです:

egrep "alias [[:alnum:]]+" local_alias -o|while read i; do
  un$i
done

真ん中の行を に変更するとecho un$i、出力は適切にフォーマットされたunaliasコマンドのように見えます: unalias foo。しかし、記述どおりだと になりますunalias: foo: not found

真ん中の行を引用しようとすると"un$i"、代わりに になりますunalias foo: command not found

何が間違っているのでしょうか?

答え1

エイリアスはシェルに固有のものなので、次のようにスクリプトを実行します。

#!/bin/bash

...
unalias ....
...

これは子シェルとして実行されており、通常は同じエイリアスを持ちません。問題をさらに複雑にしているのは、別の問題にも対処しているということです。スクリプトが終了するとすぐに、エイリアスが削除された子シェルは消え、エイリアスがそのまま残っている親シェルに戻ります。

現在のシェルのエイリアスをこのように変更する方法は、私の知る限りありません。

それで、これをどうやって行うのでしょうか?

このアクションを実行するには、現在のシェル自体のスコープ内でエイリアスまたは関数を構築できます。

エイリアスソリューション

$ alias unalias_local='egrep "alias [[:alnum:]]+" local_alias -o|while read i; do un$i; done'

関数ソリューション

$ function unalias_local { egrep "alias [[:alnum:]]+" local_alias -o | \
    while read i; do un$i; done; }

上記の問題点

OP はこの回答に対してこれらのソリューションを提供し、自分のシナリオでは機能すると述べています。ただし、一般に、このようなパイプ コマンドのチェーン内のエイリアスを変更することはできません。各パイプはサブシェルを呼び出し、サブシェルは親のシェルにアクセスできないためです。そのため、スクリプトで以前と同じ問題に戻ってしまいます。

この問題を回避するには、代わりにコマンドの引数としてエイリアスのリストを指定します。

$ alias ali1="cmd1"
$ alias ali2="cmd2"

シェルでエイリアスを確認します。

$ alias | grep -E "ali[12]"
alias ali1='cmd1'
alias ali2='cmd2'

の内容local_alias

$ cat local_alias 
alias ali1="cmd1"
alias ali2="cmd2"

このコマンドは、ファイルからエイリアスの名前を解析しますlocal_alias:

$ grep -oP "(?<=alias )([[:alnum:]]+)" local_alias
ali1
ali2

unalias次のようにしてこれらのエイリアスに使用できます。

$ unalias $(grep -oP "(?<=alias )([[:alnum:]]+)" local_alias)
$

彼らがいなくなったことを確認したら:

$ alias | grep -E "ali[12]"
$

答え2

このコードを別のスクリプトで実行しているようです。これはうまくいきません。実行中のシェルの設定を変更する必要がありますが、別のプロセスから変更することはできません。このクリーンアップ コードは、 で定義された関数内にある必要があります.bashrc

2 つ目の問題は、パイプによってサブプロセス (サブシェル) も作成されることです。したがって、このコードを対話型シェル内で実行すると、コマンドによってエイリアスが削除されますが、削除されるのはサブシェル内のみです。サブシェル内でコマンドunaliasを実行しない別の方法が必要です。unalias

解決策はいくつかありますが、最も簡単なのは、エイリアスのリストを作成し、コマンドをunalias1 回実行することです。エイリアス名には特殊文字を含めることができないため、エイリアスのリストで単語を分割すると、 への引数を生成できますunalias

unalias $(egrep -o "alias [[:alnum:]]+" local_alias)

関連情報