An eine PATH-ähnliche Variable anhängen, ohne einen führenden Doppelpunkt zu erstellen, wenn dieser nicht gesetzt ist

10

Ich muss ein Verzeichnis anhängen PKG_CONFIG_PATH. Normalerweise würde ich den Standard verwenden

export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:$(pyenv prefix)/lib/pkgconfig

wurde aber PKG_CONFIG_PATHbisher noch nicht auf meinem System eingestellt. Daher beginnt die Variable mit einem :Zeichen, das sie anweist, zuerst im aktuellen Verzeichnis zu suchen. Ich möchte das nicht. Ich entschied mich für Folgendes:

export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}${PKG_CONFIG_PATH:+:}$(pyenv prefix)/lib/pkgconfig

aber das scheint einfach so hässlich. Gibt es einen besseren Weg? Was ist der geeignete Weg, um den Doppelpunkt genau dann bedingt anzuhängen, wenn die Variable bereits festgelegt wurde?

scottbb
quelle
1
stackoverflow.com/questions/9631228/…
sancho.s Reinstate Monica

Antworten:

13

Sie sind mit dem ${:+}Erweiterungsoperator auf dem richtigen Weg , Sie müssen ihn nur geringfügig ändern:

V=${V:+${V}:}new_V

Die ersten geschweiften Klammern werden erweitert $V und der Doppelpunkt iff Vwird bereits anderweitig auf nichts gesetzt - genau das, was Sie benötigen (und wahrscheinlich auch einer der Gründe für die Existenz des Operators).

Also in Ihrem Fall:

export "PKG_CONFIG_PATH=${PKG_CONFIG_PATH:+${PKG_CONFIG_PATH}:}$(pyenv prefix)/lib/pkgconfig"
Peterph
quelle
Ich war diese Form, aber ich entschied sich dagegen , weil es (etwas) fühlte sich weniger lesbar: ${V}${V:+:}Wvs ${V:+${V}:}W. In jedem Fall fühlen sich beide sehr hässlich. Ich hatte auf etwas gehofft ... eleganter, denke ich?
Scottbb
@scottbb - das ist die Syntaxform - so wird es gemacht. Wenn Sie den Wert einer Variablen basierend auf einer Bedingung festlegen möchten, müssen Sie einen Test durchführen. Sie können einen Inline-Test durchführen, wie hier beschrieben, oder Sie können explizit mit testen test- so oder so, wie Sie den Wert testen und den Variablennamen zweimal schreiben, aber auf diese Weise tun Sie dies in einer einzigen Ausführungsanweisung - auf diese Weise ist es praktisch , aber ich habe noch nie einen eleganten Computer getroffen.
Mikesserv
@scottbb Wenn ich daran denke, ist es wirklich dasselbe. Aber ich fürchte, Sie werden es nicht besser bekommen, da Sie im Grunde den Variablennamen in der Bedingung und dann in der Erweiterung benötigen - ich glaube nicht, dass es ein Shell-Konstrukt gibt, das dies mit nur einem Vorkommen von tun würde Name.
Peterph
@mikeserv - Ich hätte wahrscheinlich präziser sein sollen, als zu sagen, dass ich nach einer "eleganteren" Lösung gesucht habe. Ich habe noch nie gesehen, dass dies getan wurde, um Teilzeichenfolgen an Variablen im PATH-Stil anzuhängen, und es fühlte sich irgendwie so an, als würde mir ein besserer Weg fehlen. Nach meiner Erfahrung gibt es normalerweise einen besseren Weg, wenn ich dieses Gefühl bekomme. Das hätte ich sagen sollen. Aber Ihr Punkt ist gut aufgenommen. Vielen Dank für Ihre Antwort. Außerdem: In einer Ihrer Änderungen des Kommentars von @ peterph haben Sie den Kommentar abgegeben, zu dem ich das gesamte Argument hätte zitieren sollen export. Das ist ein sehr guter Punkt, ich habe auch dieses Detail verärgert.
Scottbb
@scottbb - Entschuldigung, wenn sich das als abrasiv herausstellte - ich habe das Konzept der Eleganz in Bezug auf Computer nie verstanden . Ein Computer ist eine Maschine - ein Dreiwege- und / oder Tor, das milliardenfach zusammengesetzt ist. es kann nicht höher als eins zählen - in jeder Hinsicht ist alles, was es tut, brutal gezwungen . Einige intuitive Konzepte sind möglicherweise einfacher zu übersetzen als andere, aber wenn ja, nur, weil das Konzept auf einer anderen brutalen Abstraktion steht. Computing ist im Kern immer alles andere als elegant.
Mikesserv
1

In letzter Zeit stelle ich GNU Stow auf meine Maschinen zum Speichern von Benutzerweiten Sachen wie Bibliotheken unter ~/.localund lief in Schwierigkeiten bei der Definition LD_LIBRARY_PATH, CPATHund LIBRARY_PATHversehentlich einen Doppelpunkt dort setzen und so Sachen zu brechen.

Dann fand ich Ihre Frage und die Antwort war nicht gerade elegant ;-), und ich schrieb eine kleine Funktion, um dies zu handhaben. Sie finden sie hier: https://gist.github.com/rico-chet/0229e4c080d9f51a02535dd25a656a8a

## Copyright (C) 2018 Alex Thiessen <[email protected]>
## Copyright (C) 2018 /unix//users/116858/kusalananda
## SPDX-License-Identifier: GPL-2.0-or-later
## <https://spdx.org/licenses/GPL-2.0-or-later.html>

function join() {
    if [ ${#} -eq 0 ]
    then
        echo "\`join\` appends elements separated by colons to a \`bash\` variable " >&2
        echo "usage: join <variable> <element> [element ...]" >&2
        return 1
    fi
    variable="${1}"

    shift
    export ${variable}="${!variable:+${!variable}:}$(IFS=:; echo "${*}")"
}

// bearbeitet wie von @Kusalananda vorgeschlagen

Superlexx
quelle
Auch:( IFS=:; set -- 1 2 3 4 5 6; echo "$*" )
Kusalananda
Dh:join () { var=$1; shift; export "$var"="$( IFS=:; echo "$*" )"; }
Kusalananda
... Außer dass "join" ein unglücklicher Name ist, da es auch der Name eines Standarddienstprogramms ist.
Kusalananda
Schön, bis auf die Tatsache, dass Sie die Variable überschreiben würden, anstatt sie anzuhängen. Nur das Hinzufügen ${!variable:+${!variable}:}an der richtigen Stelle hat für mich funktioniert, alle Tests bestanden. Das Finden eines geeigneten Namens ist eine Übergröße für den Leser :)
Superlexx