Wenn der integrierte Befehl bash set
ohne Argumente aufgerufen wird, werden alle Shell- und Umgebungsvariablen, aber auch alle definierten Funktionen gedruckt. Dies macht die Ausgabe für den Menschen unbrauchbar und schwierig grep
.
Wie kann ich den eingebauten Bash-Befehl veranlassen set
, nur die Variablen und nicht die Funktionen zu drucken?
Gibt es andere Befehle, die nur die Shell-Variablen ohne die Funktionen ausgeben?
Hinweis: bash unterscheidet zwischen Shell-Variablen und Umgebungsvariablen. siehe hier Unterschied zwischen Umgebungsvariablen und exportierten Umgebungsvariablen in bash
quelle
_
, die leicht zu entfernen sind:(set -o posix ; set | grep -v ^_)
set -o posix; set | sed -e '/^_/,$d'; set +o posix;
(set -o posix; set)
. Ohne die Klammern würde sich das Verhalten der aktuellen Bash-Shell an den Posix-Standard anpassen. (Keine Ahnung, was das bedeutet, aber es sieht wichtig aus.) Mit den Klammern bleibt die Bash unverändert.POSIXLY_CORRECT=y
und fügtposix
an$SHELLOPTS
Hier sind einige Problemumgehungen:
Nervenzusammenbruch:
declare
druckt jede definierte Variable (exportiert oder nicht) und Funktion.declare -f
druckt nur Funktionen.comm -3
entfernt alle beiden gemeinsamen Zeilen. Tatsächlich werden dadurch die Funktionen entfernt, und nur die Variablen bleiben erhalten.So drucken Sie nur Variablen, die nicht exportiert werden:
Eine andere Problemumgehung:
Dadurch werden nur die Variablen mit einigen hässlichen Attributen gedruckt.
Sie können die Attribute mit ... cut entfernen:
Ein Nachteil ist, dass der Wert von IFS interpretiert und nicht angezeigt wird.
vergleichen Sie:
Dies macht es ziemlich schwierig, diese Ausgabe für die weitere Verarbeitung zu verwenden, da sie nur
"
in einer Zeile vorhanden ist. Vielleicht kann etwas IFS-Fu getan werden, um dies zu verhindern.Noch eine Problemumgehung mit
compgen
:Die eingebaute Bash
compgen
sollte in Vervollständigungsskripten verwendet werden. Zu diesem Zweckcompgen -v
werden alle definierten Variablen. Der Nachteil: Es werden nur die Variablennamen aufgeführt, nicht die Werte.Hier ist ein Hack, um auch die Werte aufzulisten.
Der Vorteil: Es ist eine reine Bash-Lösung. Der Nachteil: Einige Werte sind durch die Interpretation durcheinander
printf
. Auch die Subshell aus der Pipe und / oder der Schleife fügt einige zusätzliche Variablen hinzu.quelle
declare ...| cut
Pipe, wenn es keine Attribute für eine Variable gibt? Ich vermute,--
das wird in diesem Fall verwendet, aber ich bin immer noch unruhig.sed
könnte sicherer sein, dhdeclare -p | sed 's/^.* \([^ ]\+\)$/\1/'
compgen
:)Das
typeset
eingebaute hat seltsamerweise die Option, nur Funktionen anzuzeigen (-f
), aber nicht nur Parameter. Glücklicherweise zeigttypeset
(oderset
) alle Parameter an, bevor alle Funktionen, Funktions- und Parameternamen keine Zeilenumbrüche oder Gleichheitszeichen enthalten können, und Zeilenumbrüche in Parameterwerten werden in Anführungszeichen gesetzt (sie erscheinen als\n
). Sie können also in der ersten Zeile anhalten, die kein Gleichheitszeichen enthält:Hiermit werden nur die Parameternamen gedruckt. Wenn Sie die Werte möchten, ändern Sie
print $1
zuprint $0
.Beachten Sie, dass hiermit alle Parameternamen gedruckt werden (Parameter und Variablen werden hier synonym verwendet), nicht nur Umgebungsvariablen („Umgebungsvariable“ ist synonym mit „exportierten Parametern“).
Beachten Sie auch, dass davon ausgegangen wird, dass es keine Umgebungsvariable mit einem Namen gibt, der nicht den Einschränkungen von bash für Parameternamen entspricht. Solche Variablen können nicht innerhalb von bash erstellt werden, sondern können zu Beginn von bash von der Umgebung geerbt worden sein:
quelle
set | sed '/=/!Q'
Ich bin mir nicht sicher, wie man
set
nur Variablen drucken kann. Wennset
ich mir jedoch die Ausgabe von anschaue , konnte ich Folgendes herausfinden, das nur Variablen zu erfassen scheint:Grundsätzlich suche ich nach Zeilen, die mit Buchstaben, Zahlen oder Interpunktion beginnen, gefolgt von einem "=". Aus der Ausgabe, die ich gesehen habe, werden alle Variablen erfasst. Ich bezweifle jedoch, dass dies sehr portabel ist.
Wenn Sie, wie Ihr Titel schon sagt, die exportierten Variablen von dieser Liste abziehen möchten, um eine Liste der nicht exportierten Variablen zu erhalten, können Sie so etwas tun
Um dies ein wenig aufzuschlüsseln, ist hier, was es tut:
set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" | sort > ./setvars
: Damit werden hoffentlich alle Variablen (wie oben beschrieben) abgerufen, sortiert und das Ergebnis in einer Datei gespeichert.&& env | sort
: Nachdem der vorherige Befehl abgeschlossen ist, rufen wirenv
seine Ausgabe auf und sortieren sie.| comm -23 ./setvars -
: Schließlich leiten wir die sortierte Ausgabe vonenv
in umcomm
und verwenden die-23
Option, um die Zeilen zu drucken, die für das erste Argument eindeutig sind, in diesem Fall die Zeilen, die für unsere Ausgabe von set eindeutig sind.Wenn Sie fertig sind, möchten Sie möglicherweise die temporäre Datei bereinigen, die mit dem Befehl erstellt wurde
rm ./setvars
quelle
f () {|cat <<EOF|foo=bar|EOF|}
wobei|
ein Zeilenumbruch dargestellt wird).Verwenden Sie einfach den Befehl
env
. Es werden keine Funktionen gedruckt.quelle
Versuchen Sie den Befehl printenv:
quelle
In bash werden nur Variablennamen ausgegeben:
Oder, wenn auch Werte benötigt werden, verwenden Sie:
quelle
Ein Unterschied zu einer sauberen Shell, um sicherzustellen, dass auch Variablen aus RC-Skripten ausgelassen werden
die version mit
comm
wäre zu kompliziertquelle
Die akzeptierte Antwort ist großartig. Ich biete eine Alternative an, bei der der POSIX-Modus nicht festgelegt wird:
Hier ist die Technik, mit der ich den Funktionsstatus in einer Datei gespeichert habe, damit ich ihn später fortsetzen kann. Das erste erzeugt einen State Dump und das zweite erzeugt nur eine Liste der Variablennamen.
Beide arbeiten so lange, bis eine Zeile ohne '=' Zeichen gefunden wird. Dies tritt auf, wenn die erste Funktion aufgelistet wird. Letzterer beendet den Auftrag.
quelle