Generieren von Befehlen mit variabler Erweiterung in einer Schleife

Generieren von Befehlen mit variabler Erweiterung in einer Schleife

Ich möchte lokale Aliase erstellen, während ich in bestimmten Verzeichnissen arbeite. Beispielsweise möchte ich Folgendes in einer Datei namens habenlocal_alias

alias foo='bar'

Ich wollte ein Bereinigungsskript schreiben, um diese Aliase zu entfernen, nachdem ich mit der Arbeit fertig bin. So etwas wie:

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

Wenn ich die mittlere Zeile in ändere echo un$i, sieht die Ausgabe aus wie ein ordnungsgemäß formatierter unaliasBefehl: unalias foo. So wie ich sie schreibe, erhalte ich jedoch unalias: foo: not found.

Wenn ich versuche, die mittlere Zeile zu zitieren: "un$i", erhalte ich stattdessen unalias foo: command not found.

Was mache ich falsch?

Antwort1

Die Aliase sind spezifisch für die Shell. Wenn Sie Ihr Skript also folgendermaßen ausführen:

#!/bin/bash

...
unalias ....
...

Es läuft als untergeordnete Shell, die normalerweise nicht dieselben Aliase hat. Das Problem wird noch dadurch verschärft, dass Sie sich auch mit einem weiteren Problem auseinandersetzen müssen. Sobald das Skript beendet wird, verschwindet die untergeordnete Shell, deren Aliase entfernt wurden, und Sie kehren zur übergeordneten Shell zurück, deren Aliase noch intakt sind.

Mir ist keine Möglichkeit bekannt, die Aliase Ihrer aktuellen Shell auf diese Weise zu ändern.

Wie also geht das dann?

Sie können einen Alias ​​oder eine Funktion im Gültigkeitsbereich der aktuellen Shell selbst erstellen, um diese Aktion auszuführen.

Beispiel

Alias-Lösung

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

Funktionslösung

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

Probleme mit den oben genannten

Der OP lieferte diese Lösungen für diese Antwort, von denen er angab, dass sie in seinem Szenario funktionieren würden. Aber im Allgemeinen können Sie die Aliase in einer Kette von Pipe-Befehlen wie dieser nicht ändern, da jede Pipe eine Subshell aufruft, die die Shell des übergeordneten Elements nicht berühren kann. Wir sind also wieder beim gleichen Problem wie zuvor mit dem Skript.

Um dies zu umgehen, können Sie stattdessen die Liste der Aliase als Argumente für einen Befehl bereitstellen.

Beispiel

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

Bestätigen Sie die Aliase in unserer Shell:

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

Inhalt von local_alias:

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

Dieser Befehl analysiert die Namen der Aliase aus der Datei local_alias:

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

unaliasWir können es für diese Aliase wie folgt verwenden :

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

Wenn wir nun bestätigen, dass sie weg sind:

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

Antwort2

Es scheint, dass Sie diesen Code in einem separaten Skript ausführen. Das geht nicht: Sie müssen die Konfiguration Ihrer laufenden Shell ändern, und das können Sie nicht von einem anderen Prozess aus tun. Dieser Bereinigungscode sollte in einer in Ihrem definierten Funktion enthalten sein .bashrc.

Ein zweites Problem ist, dass die Pipe auch einen Unterprozess (eine Untershell) erstellt. Wenn Sie diesen Code also in Ihrer interaktiven Shell ausführen, entfernt der Befehl den Alias ​​– aber nur in der Untershell. Sie benötigen einen anderen Ansatz, der den Befehl nicht in einer Untershell unaliasausführt .unalias

Es gibt mehrere Lösungen, aber die einfachste wäre, die Liste der Aliase zu erstellen und dann den unaliasBefehl einmal auszuführen. Aliasnamen dürfen keine Sonderzeichen enthalten, daher reicht die Worttrennung in der Liste der Aliase aus, um die Argumente für zu generieren unalias.

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

verwandte Informationen