我想在某些目錄中工作時建立本地別名。例如,我想在名為的檔案中包含以下內容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
別名是特定於 shell 的,因此當您像這樣執行腳本時:
#!/bin/bash
...
unalias ....
...
它作為子 shell 運行,通常不會具有相同的別名。讓問題更加複雜的是,您還要處理另一個問題。一旦腳本終止,別名已被刪除的子 shell 就會消失,返回父 shell,其別名仍然完好無損。
據我所知,無法以這種方式修改目前 shell 的別名。
那麼如何做到這一點呢?
您可以在目前 shell 本身的範圍內建構一個別名或函數來執行此操作。
例子
別名解決方案
$ 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 為這個答案提供了這些解決方案,他說這些解決方案將在他的場景中發揮作用。但一般來說,您不能像這樣更改管道命令鏈中的別名,因為每個管道都會呼叫一個子 shell,而該子 shell 將無法觸及父 shell。所以我們又回到了與之前腳本相同的問題。
為了解決這個問題,您可以提供別名清單作為命令的參數。
例子
$ alias ali1="cmd1"
$ alias ali2="cmd2"
在我們的 shell 中確認別名:
$ 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
您似乎在單獨的腳本中運行此程式碼。這是行不通的:您需要更改正在運行的 shell 的配置,並且無法從另一個進程執行此操作。此清理代碼應該位於您的.bashrc
.
第二個問題是管道也創建一個子進程(子shell)。因此,如果您在互動式 shell 中執行此程式碼,則該unalias
命令將刪除別名 - 但僅在子 shell 中。您需要一種不在unalias
子 shell 中運行命令的不同方法。
有多種解決方案,但最簡單的一種是建立別名列表,然後執行命令unalias
一次。別名不能包含特殊字符,因此別名列表上的單字分割可以很好地生成unalias
.
unalias $(egrep -o "alias [[:alnum:]]+" local_alias)