在循環中產生帶有變數擴展的命令

在循環中產生帶有變數擴展的命令

我想在某些目錄中工作時建立本地別名。例如,我想在名為的檔案中包含以下內容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)

相關內容