Dies ersetzt all :in $PATHdurch eine neue Zeile ( \n) und gibt das Ergebnis aus. Der Inhalt von $PATHbleibt unverändert.
Wenn Sie nur den ersten ersetzen möchten :, entfernen Sie den zweiten Schrägstrich:echo -e "${PATH/:/\n}"
Ich denke, dass dies die beste Lösung ist, weil es in purer Bash gemacht wird.
Ryanmjacobs
1
@ryanmjacobs milde neugierig: was denkst du nutzt meine lösung? : D
muru
1
Bitte erläutern Sie, wie es funktioniert.
Tulains Córdova
Wie heißt diese Operation? Es ist ähnlich wie sed, aber es ist nicht sed. Wie heißt es, damit ich im Internet nach weiteren Informationen suchen kann?
Tulains Córdova
3
Folgen Sie dem Link (Parameter Expansion) in meiner Antwort und scrollen Sie zum letzten zweiten Abschnitt mit dem Namen:${parameter/pattern/string}
Cyrus
27
Verwendung von IFS:
(set-f; IFS=:; printf "%s\n" $PATH)
IFSEnthält die Zeichen, für die die Bash-Aufteilung ausgeführt wird. IFSMit :der Option with wird die Aufteilung der Erweiterung von $PATHon ausgeführt :. printfSchleifen Sie die Argumente über die Formatzeichenfolge, bis die Argumente erschöpft sind. Wir müssen das Globbing (Platzhaltererweiterung) mit deaktivieren, set -fdamit Platzhalter in PATH-Verzeichnisnamen nicht erweitert werden.
Würde eine Variation davon, wie echo $PATH | xargs -n1 -d: echoredundant sein oder ist das egal?
Sergiy Kolodyazhnyy
@ Serg echo $PATH | xargs -n1 -d: wird das gleiche für Sie tun, aber Sie werden eine weitere Shell verwenden. Der erste Befehl wertet die echo $PATHAusgabe aus und leitet sie an die nächste Shell weiter, um den Rest zu erledigen.
Souravc
7
Hier ist das Äquivalent in Go:
$ cat path.go
package main
import ("fmt""os""strings")
func main(){for _, p := range strings.Split(os.Getenv("PATH"),":"){
fmt.Println(p)}}
$ go run path.go/usr/local/sbin/usr/local/bin/usr/sbin/usr/bin/sbin/bin/usr/games/usr/local/games/snap/bin/home/nathan/.local/bin/home/nathan/go/bin
Hier sind einige weitere Ansätze. Ich benutze ein PATHmit Verzeichnissen, die Backslashes, Leerzeichen und sogar eine neue Zeile enthalten, um zu zeigen, dass sie mit irgendetwas funktionieren sollten (außer dem cut, das in Newlines fehlschlägt):
$ echo "$PATH"/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even
new lines
Einige Perl-Möglichkeiten:
$ perl -pe 's/:/\n/g'<<<"$PATH"/bin
usr/bin//usr/local/bin/some\ horrible thing/even
new lines
Das -pbedeutet "drucke jede Eingabezeile nach Anwendung des von gegebenen Skripts -e". Das Skript verwendet den Substitutionsoperator ( s/oldnew/), um alle :Zeilen durch Zeilenumbrüche zu ersetzen .
$ perl -lne 'print for split /:/'<<<"$PATH"/bin
usr/bin//usr/local/bin/some\ horrible thing/even
new lines
Das -lfügt jedem printAnruf eine neue Leitung hinzu . Hier :teilt das Skript seine Eingabe auf und durchläuft dann jedes geteilte Element und druckt es aus.
$ perl -F:-ane '$"="\n";print "@F"'<<<"$PATH"/bin
usr/bin//usr/local/bin/some\ horrible thing/even
new lines
Die -aMarken perlverhalten sich wie awk: Sie teilen jede ihrer Eingabezeilen auf das von -F(also :hier) angegebene Zeichen und speichern das Ergebnis im Array @F. Das $"ist eine spezielle Perl-Variable, das "Listentrennzeichen", dessen Wert zwischen jedem Element einer gedruckten Liste gedruckt wird. Wenn Sie also eine neue Zeile festlegen, wird print @listjedes Element von @listund dann eine neue Zeile gedruckt. Hier verwenden wir es zum Drucken @F.
Gleiche Idee wie oben, nur weniger Golf. Anstatt zu verwenden $", wird joindas Array explizit mit Zeilenumbrüchen versehen und dann gedruckt.
Einfach grepmit PCRE magic:
$ grep -oP '(^|:)\K[^:]+'<<<"$PATH"/bin
usr/bin//usr/local/bin/some\ horrible thing/even
new lines
Die -oMarken grepgedruckt werden nur den passenden Abschnitt jeder Linie, so dass jedes Spiel in einer separaten Zeile gedruckt wird. Das -Paktiviert Perl-kompatible reguläre Ausdrücke (PCRE). Der Regex sucht nach Abschnitten von non- :( [^:]+), die entweder auf den Anfang der Zeile ( ^) oder auf ein :Zeichen folgen . Das \Kist ein Trick PCRE das bedeutet „Discard etwas vor diesem Punkt angepasst“ und wird hier zu vermeiden , die den Druck :als auch.
Und eine cutLösung (diese schlägt in Zeilenumbrüchen fehl, kann aber mit Backslashes und Leerzeichen umgehen):
$ cut -d:-f 1---output-delimiter=$'\n'<<<"$PATH"/bin
usr/bin//usr/local/bin/some\ horrible thing/even
new lines
Es werden folgende Optionen verwendet: -d:Setzt den Eingabebegrenzer auf :, -f 1-dh druckt alle Felder (vom 1. bis zum Ende) und --output-delimiter=$'\n'setzt den Ausgabebegrenzer. Das $'\n'ist ANSI C-Anführungszeichen und ist eine Möglichkeit, ein Zeilenumbruchzeichen in der Shell zu drucken.
In allen obigen Beispielen verwende ich den Operator string ( <<<) von bash (und einigen anderen Shells ), um einen String als Eingabe für ein Programm zu übergeben. Ist command <<<"foo"also gleichbedeutend mit echo -n "foo" | command. Beachten Sie, dass ich immer zitiere "$PATH", ohne die Anführungszeichen hätte die Shell das Zeilenumbruchszeichen gegessen.
Das nennt man Golfen . Das -0gibt das Eingabesatztrennzeichen als Oktal- oder Hexadezimalzahl an. Dies definiert eine "Linie" und ihr Standardwert ist \nein Zeilenumbruchzeichen. Hier sind wir es auf eine Einstellung , :die ist x3ain hex (Versuch printf '\x3a\n'). Das -lmacht drei Dinge. Zunächst das Eingangsdatensatztrennzeichen (entfernt $/) von dem Ende jeder Zeile effektiv Entfernen des :Hier und zweiten, den Ausgabesatz Separator (Sets $\), was auch immer Oktal oder Hexadezimalwert ihm gegeben wird ( 012ist \n). Wenn dies $\definiert ist, wird es am Ende jedes printAnrufs hinzugefügt , sodass an jeden eine neue Zeile angehängt wird print.
Der -peWille p rint jede Eingabezeile nach dem Skript von bestimmten Anwendung -e. Hier gibt es kein Skript, da die gesamte Arbeit mit den oben beschriebenen Options-Flags erledigt wird!
Ihre Perl-One-Liner sind nicht dunkel genug! Hier ist eine Version , wo es kein Code für den -en Schalter auszuführen , da die anderen Schalter alles im Griff: perl -0x3a -l012 -pe '' <<<$PATH. Erläuterung: Legt das Trennzeichen für Eingabedatensätze fest (in -0hexadezimaler / oktaler Schreibweise angegeben, x3A ist ein Doppelpunkt), -lführt zwei Aktionen aus: 1) Legt das Trennzeichen für Eingabedatensätze fest, 2) Legt das Trennzeichen für Ausgabedatensätze fest, wenn eines angegeben ist (in oktaler Schreibweise) , 012 ist ein Zeilenumbruch). Eine -pSchleife gibt den Wert von $ _ aus, der in jeder Zeile eingelesen wird.
7stud
Beachten Sie auch , dass Ihre Beispiele unter Verwendung -Fder kann beseitigen -aund -nFahnen, wie -F diejenigen , schaltet sich automatisch ein: perl -F: -e 'print(join "\n", @F);' <<<$PATH. Siehe perlrun . Schöne Beispiele.
7.
@ 7stud wow, das ist echt genial, danke! Schamlos gestohlen und zu meiner Antwort hinzugefügt (Ich nehme an, es macht Ihnen nichts aus, Sie können es gerne selbst als Antwort posten und ich werde es löschen). Und danke für die -FInfo. Ich benutze seit Jahren das -FKombinierte mit -an. Ich habe nie bemerkt, dass das eine das andere impliziert. Übrigens, ich habe gesehen, dass Serg Code Golf erwähnt hat , aber ich denke, dass Sie auch Unix und Linux mögen, wenn Sie sich für solche Dinge interessieren.
Terdon
Hey danke. Eine Klarstellung zu dieser Anweisung: Fügt schließlich -lauch das Trennzeichen für Ausgabesätze hinzu, das am Ende jedes Druckaufrufs angegeben wird. Tatsächlich fügt print das Trennzeichen für Ausgabedatensätze immer $/am Ende einer Zeichenfolge ein - wenn das Trennzeichen für Ausgabedatensätze definiert ist. Standardmäßig ist es undef. Also -lsetzt jus $/und das bewirkt, dass print die neue Zeile an das Ende der Zeichenkette anfügt.
7.
Ich nehme an, es macht Ihnen nichts aus - überhaupt nicht. :)
7stud
6
In dieser Antwort:
C
Python
Rubin
Alternative awk
1. C
Da alle Skriptsprachen bereits verwendet wurden, gehe ich zu C. Es ist ziemlich einfach, Umgebungsvariablen mit get_env()function zu erhalten (siehe GNU C Library-Dokumentation ). Der Rest ist einfach Zeichenmanipulation
Ruby wird nicht standardmäßig mit Ubuntu geliefert, im Gegensatz zu C-Compiler und Python-Interpreter. Wenn Sie es jedoch jemals verwenden, lautet die Lösung in Ruby wie folgt:
Wir können die split()Funktion verwenden, um die gelesene Zeile in ein Array aufzuteilen, und die for-eachSchleife verwenden, um jedes Element in einer separaten Zeile auszudrucken.
awk '{split($0,arr,":"); for(var in arr) print arr[var]}'<<< $PATH
Schönes Rubin Beispiel. putsdruckt die Elemente eines Arrays automatisch in separate Zeilen! Sie können auch festlegen, dass die Schalter die Aufteilung durchführen: ruby -F: -ane 'puts $F' <<<$PATH Erläuterung: -FWird $;auf das angegebene Zeichen festgelegt. Dies ist das von String :: split verwendete Standardtrennzeichen ($; hat den Standardwert nil, der auf Leerzeichen aufgeteilt wird). -aruft $ _. split auf, wobei $ _ eine mit gets ()) eingelesene Zeile ist und das resultierende Array zuweist $F.
7.
@ 7stud Hey, danke! :) Wusste nicht, dass es eine -FFlagge gibt - ich fange gerade mit Ruby an und mache die Dinge ein bisschen grob.
Sergiy Kolodyazhnyy
Nein, das ist dunkles Zeug. Ihr Einzeiler ist sehr gut lesbar und die Klarheit sollte jedes Mal die Kürze übertreffen.
7.
Hah Ich dachte , eine kürzere out: ruby -0072 -ne 'puts chomp' <<<$PATH. Erläuterung: -0Legt das Trennzeichen für Eingabesätze fest (geben Sie ein Zeichen im Oktalformat an; 072 ist ein Doppelpunkt). Ruby verwendet $ _ auf ähnliche Weise wie Perl. Die gets () -Methode (in der -nSchleife verwendet) setzt $ _ auf die aktuelle Zeile , die eingelesen wird. Und chomp()ohne ein Argument, chomps $ _. Ich mag deine immer noch besser. :)
7stud
@ 7stud Tatsächlich ist die, die Sie zuvor mit -Fflag gepostet haben, kürzer. Wenn Sie das tun echo "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c , heißt das, dass es 271 Bytes sind, aber die mit der Oktalzahl ist 276. Das gilt natürlich für den gesamten Befehl. Wenn wir nur den Code selbst betrachten, puts $Fist dieser deutlich kürzer. :) Übrigens, kennen Sie Code Golf ? Es ist die Seite für Lösungen zum Programmieren von Rätseln in kürzester Anzahl von Bytes. Es gibt eine Frage zu dieser: codegolf.stackexchange.com/q/96334/55572
Sergiy Kolodyazhnyy
5
Wahrscheinlich ist der einzige Weg, der nicht erwähnt wurde, der Weg, den ich seit Jahren benutze:
echo $PATH | tr ":" "\n"
In Ihrem .profile oder .bash_profile oder was auch immer können Sie Folgendes hinzufügen:
Ich bin mir nicht sicher, warum Sie sich die Mühe machen, fileinputwenn Sie nur verwenden könnten input:python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
wjandrea
2
Ich benutze Stephen Collyers "Bash Path Functions" (siehe seinen Artikel im Linux Journal ). Es erlaubt mir, die "durch Doppelpunkte getrennte Liste" als Datentyp in der Shell-Programmierung zu verwenden. Zum Beispiel kann ich eine Liste aller Verzeichnisse im aktuellen Verzeichnis erstellen, indem ich:
dirs="";for i in*;doif[-d $i ];then addpath -p dirs $i;fi;done
Shell Parameter Expansion - erklärt $ {parameter / pattern / string}. Wenn pattern mit '/' beginnt, werden alle Übereinstimmungen von pattern durch string ersetzt.
Also haben wir:
ein Muster /: das mit '/' beginnt, um alle Übereinstimmungen zu ersetzen
ein String $ '\ n', der mit $ 'anytext' -Kontraktion in Anführungszeichen gesetzt wird, um das neue Liniensymbol (\ n) zu behandeln.
Eine andere AWK-Methode besteht darin, jedes Verzeichnis als separaten Datensatz und nicht als separates Feld zu behandeln .
awk 'BEGIN{RS=":"} {print $0}'<<<"$PATH"
Ich finde diese Syntax besonders intuitiv. Wenn Sie möchten, können Sie es jedoch verkürzen, indem Sie das print $0implizite Element festlegen (dies ist die Standardaktion, 1die mit true ausgewertet wird und für jede Zeile ausgeführt wird):
awk 'BEGIN{RS=":"} 1'<<<"$PATH"
Das standardmäßige Eingabe- und Ausgabesatztrennzeichen von AWK ist der Zeilenumbruch. Durch Setzen des Trennzeichens ( RS) für :Eingabedatensätze vor dem Lesen der Eingabe analysiert AWK automatisch einen durch Doppelpunkte getrennten Namen $PATHin den konstituierenden Verzeichnisnamen. AWK wird $0auf jeden vollständigen Datensatz erweitert, die neue Zeile bleibt das Trennzeichen für den Ausgabedatensatz , und es ist keine Schleife gsuberforderlich.
AWK wird häufig zum Parsen von Datensätzen in separate Felder verwendet, es ist jedoch nicht erforderlich, lediglich eine Liste von Verzeichnisnamen zu erstellen.
Dies funktioniert auch für Eingaben mit Leerzeichen (Leerzeichen und Tabulatoren) und mehreren aufeinanderfolgenden Leerzeichen:
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}'<<<$'ab\t\t c:de fg:h'
ab c
de fg
h
Das heißt, es sei denn, Sie veranlassen AWK , den Datensatz neu zu erstellen (siehe unten), ist es kein Problem, Leerzeichen oder Tabulatoren (die Standardfeldtrennzeichen) in der Eingabe zu haben. Ihr enthält PATHwahrscheinlich keine Leerzeichen auf einem Ubuntu-System, aber wenn dies der Fall ist, funktioniert dies immer noch.
Es ist erwähnenswert, als eine Randnotiz, dass AWK Fähigkeit eine Aufzeichnung als eine Sammlung von Feldern zu interpretieren wird , die für das damit verbundene Problem der Konstruktion eine Tabelle von Verzeichnis Komponenten :
ek@Io:~$ awk -F/'BEGIN{RS=":"; OFS="\t"} {$1=$1; print $0}'<<<"$PATH"
home ek bin
usr local sbin
usr local bin
usr sbin
usr bin
sbin
bin
usr games
usr local games
snap bin
(Dies ist wahrscheinlich nützlicher für Fälle, in denen zusätzliche Verarbeitung für die Komponenten ausgeführt werden soll, als für das genaue gezeigte Beispiel des einfachen Druckens der Tabelle.)
Dies sind meine bevorzugten Methoden, basierend auf meinen jeweiligen Anwendungsfällen und Bedenken hinsichtlich Kompatibilität und Ressourcennutzung.
tr
Wenn Sie eine schnelle, leicht zu merkende und lesbare Lösung benötigen, wiederholen Sie diese und leiten Sie PATHsie an translate ( tr) weiter , um die Doppelpunkte in Zeilenumbrüche umzuwandeln:
echo $PATH | tr :"\n"
Es hat den Nachteil, dass aufgrund der Pipe zwei Prozesse verwendet werden, aber wenn wir nur in ein Terminal hacken, interessiert uns das wirklich?
Bashs Shell-Parameter-Erweiterung
Wenn Sie eine relativ dauerhafte Lösung .bashrcfür die interaktive Verwendung wünschen , können Sie den folgenden Befehl als Alias verwenden path, die Lesbarkeit dieser Lösung ist jedoch fraglich:
alias path="echo \"${PATH//:/$'\n'}\""
Wenn das Muster mit '/' beginnt, werden alle Übereinstimmungen des Musters durch eine Zeichenfolge ersetzt. Normalerweise wird nur die erste Übereinstimmung ersetzt.
Der obige Befehl ersetzt den Doppelpunkt mit Zeilenumbrüchen unter Verwendung der Shell-Parametererweiterung von Bash :
${parameter/pattern/string}
Um es zu erklären:
# v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"# ^^ ^^^^^----string, $ required to get newline character.# \----------pattern, / required to substitute for *every* :.
Viel Glück, wenn Sie sich daran erinnern, wenn Sie nur über die Befehlszeile hacken, wenn Sie es aber nicht geglättet haben.
IFS, getestet in Bash und Dash
Alternativ können Sie die folgende Funktion verwenden, wenn Sie einen ziemlich kompatiblen, lesbaren und verständlichen Ansatz verfolgen, der sich auf nichts anderes als die Shell stützt (ich schlage in Ihrem Beispiel vor .bashrc).
Die folgende Funktion macht das interne (oder Eingabe-) Feldtrennzeichen (IFS) vorübergehend zu einem Doppelpunkt, und wenn ein Array übergeben wird, printfwird es ausgeführt, bis das Array aufgebraucht ist:
path (){local IFS=:
printf "%s\n" ${PATH}}
Diese Methode der Funktion Schöpfung , IFSund printfsind für die von Posix vorgesehen, so dass es in den meisten Posix artigen Schalen funktionieren sollte (vor allem Dash, die Ubuntu in der Regel Aliase wie sh).
Python
Solltest du dafür Python verwenden? Du könntest. Dies ist der kürzeste Python-Befehl, den ich mir vorstellen kann:
Antworten:
Versuchen Sie
sed
:Oder
tr
:Oder
python
:Hier werden alle oben genannten Punkte
:
durch neue Zeilen ersetzt\n
.quelle
python -c 'import sys;print sys.argv[1].replace(":","\n")' $PATH
python -c "print r'$PATH'.replace(':', '\n')"
(mit einem rohen String im Falle von Backslashes)tr
arbeitete für mich (auf dem Mac, übrigens). Vielen Dank..bash_profile
es wie folgt:alias path='tr ":" "\n" <<< "$PATH"'
Verwenden Sie die Parametererweiterung von bash :
Dies ersetzt all
:
in$PATH
durch eine neue Zeile (\n
) und gibt das Ergebnis aus. Der Inhalt von$PATH
bleibt unverändert.Wenn Sie nur den ersten ersetzen möchten
:
, entfernen Sie den zweiten Schrägstrich:echo -e "${PATH/:/\n}"
quelle
${parameter/pattern/string}
Verwendung von IFS:
IFS
Enthält die Zeichen, für die die Bash-Aufteilung ausgeführt wird.IFS
Mit:
der Option with wird die Aufteilung der Erweiterung von$PATH
on ausgeführt:
.printf
Schleifen Sie die Argumente über die Formatzeichenfolge, bis die Argumente erschöpft sind. Wir müssen das Globbing (Platzhaltererweiterung) mit deaktivieren,set -f
damit Platzhalter in PATH-Verzeichnisnamen nicht erweitert werden.quelle
Verwenden von
xargs
:Von
man xargs
quelle
echo $PATH | xargs -n1 -d: echo
redundant sein oder ist das egal?echo $PATH | xargs -n1 -d:
wird das gleiche für Sie tun, aber Sie werden eine weitere Shell verwenden. Der erste Befehl wertet dieecho $PATH
Ausgabe aus und leitet sie an die nächste Shell weiter, um den Rest zu erledigen.Hier ist das Äquivalent in Go:
quelle
Hier sind einige weitere Ansätze. Ich benutze ein
PATH
mit Verzeichnissen, die Backslashes, Leerzeichen und sogar eine neue Zeile enthalten, um zu zeigen, dass sie mit irgendetwas funktionieren sollten (außer demcut
, das in Newlines fehlschlägt):Einige Perl-Möglichkeiten:
Das
-p
bedeutet "drucke jede Eingabezeile nach Anwendung des von gegebenen Skripts-e
". Das Skript verwendet den Substitutionsoperator (s/oldnew/
), um alle:
Zeilen durch Zeilenumbrüche zu ersetzen .Das
-l
fügt jedemprint
Anruf eine neue Leitung hinzu . Hier:
teilt das Skript seine Eingabe auf und durchläuft dann jedes geteilte Element und druckt es aus.Die
-a
Markenperl
verhalten sich wieawk
: Sie teilen jede ihrer Eingabezeilen auf das von-F
(also:
hier) angegebene Zeichen und speichern das Ergebnis im Array@F
. Das$"
ist eine spezielle Perl-Variable, das "Listentrennzeichen", dessen Wert zwischen jedem Element einer gedruckten Liste gedruckt wird. Wenn Sie also eine neue Zeile festlegen, wirdprint @list
jedes Element von@list
und dann eine neue Zeile gedruckt. Hier verwenden wir es zum Drucken@F
.Gleiche Idee wie oben, nur weniger Golf. Anstatt zu verwenden
$"
, wirdjoin
das Array explizit mit Zeilenumbrüchen versehen und dann gedruckt.Einfach
grep
mit PCRE magic:Die
-o
Markengrep
gedruckt werden nur den passenden Abschnitt jeder Linie, so dass jedes Spiel in einer separaten Zeile gedruckt wird. Das-P
aktiviert Perl-kompatible reguläre Ausdrücke (PCRE). Der Regex sucht nach Abschnitten von non-:
([^:]+
), die entweder auf den Anfang der Zeile (^
) oder auf ein:
Zeichen folgen . Das\K
ist ein Trick PCRE das bedeutet „Discard etwas vor diesem Punkt angepasst“ und wird hier zu vermeiden , die den Druck:
als auch.Und eine
cut
Lösung (diese schlägt in Zeilenumbrüchen fehl, kann aber mit Backslashes und Leerzeichen umgehen):Es werden folgende Optionen verwendet:
-d:
Setzt den Eingabebegrenzer auf:
,-f 1-
dh druckt alle Felder (vom 1. bis zum Ende) und--output-delimiter=$'\n'
setzt den Ausgabebegrenzer. Das$'\n'
ist ANSI C-Anführungszeichen und ist eine Möglichkeit, ein Zeilenumbruchzeichen in der Shell zu drucken.In allen obigen Beispielen verwende ich den Operator string (
<<<
) von bash (und einigen anderen Shells ), um einen String als Eingabe für ein Programm zu übergeben. Istcommand <<<"foo"
also gleichbedeutend mitecho -n "foo" | command
. Beachten Sie, dass ich immer zitiere"$PATH"
, ohne die Anführungszeichen hätte die Shell das Zeilenumbruchszeichen gegessen.@ 7stud gab einen anderen Ansatz in den Kommentaren an , der einfach zu gut ist, um ihn nicht einzuschließen :
Das nennt man Golfen . Das
-0
gibt das Eingabesatztrennzeichen als Oktal- oder Hexadezimalzahl an. Dies definiert eine "Linie" und ihr Standardwert ist\n
ein Zeilenumbruchzeichen. Hier sind wir es auf eine Einstellung ,:
die istx3a
in hex (Versuchprintf '\x3a\n'
). Das-l
macht drei Dinge. Zunächst das Eingangsdatensatztrennzeichen (entfernt$/
) von dem Ende jeder Zeile effektiv Entfernen des:
Hier und zweiten, den Ausgabesatz Separator (Sets$\
), was auch immer Oktal oder Hexadezimalwert ihm gegeben wird (012
ist\n
). Wenn dies$\
definiert ist, wird es am Ende jedesprint
Anrufs hinzugefügt , sodass an jeden eine neue Zeile angehängt wirdprint
.Der
-pe
Wille p rint jede Eingabezeile nach dem Skript von bestimmten Anwendung-e
. Hier gibt es kein Skript, da die gesamte Arbeit mit den oben beschriebenen Options-Flags erledigt wird!quelle
perl -0x3a -l012 -pe '' <<<$PATH
. Erläuterung: Legt das Trennzeichen für Eingabedatensätze fest (in-0
hexadezimaler / oktaler Schreibweise angegeben, x3A ist ein Doppelpunkt),-l
führt zwei Aktionen aus: 1) Legt das Trennzeichen für Eingabedatensätze fest, 2) Legt das Trennzeichen für Ausgabedatensätze fest, wenn eines angegeben ist (in oktaler Schreibweise) , 012 ist ein Zeilenumbruch). Eine-p
Schleife gibt den Wert von $ _ aus, der in jeder Zeile eingelesen wird.-F
der kann beseitigen-a
und-n
Fahnen, wie -F diejenigen , schaltet sich automatisch ein:perl -F: -e 'print(join "\n", @F);' <<<$PATH
. Siehe perlrun . Schöne Beispiele.-F
Info. Ich benutze seit Jahren das-F
Kombinierte mit-an
. Ich habe nie bemerkt, dass das eine das andere impliziert. Übrigens, ich habe gesehen, dass Serg Code Golf erwähnt hat , aber ich denke, dass Sie auch Unix und Linux mögen, wenn Sie sich für solche Dinge interessieren.-l
auch das Trennzeichen für Ausgabesätze hinzu, das am Ende jedes Druckaufrufs angegeben wird. Tatsächlich fügt print das Trennzeichen für Ausgabedatensätze immer$/
am Ende einer Zeichenfolge ein - wenn das Trennzeichen für Ausgabedatensätze definiert ist. Standardmäßig ist es undef. Also-l
setzt jus$/
und das bewirkt, dass print die neue Zeile an das Ende der Zeichenkette anfügt.In dieser Antwort:
1. C
Da alle Skriptsprachen bereits verwendet wurden, gehe ich zu C. Es ist ziemlich einfach, Umgebungsvariablen mit
get_env()
function zu erhalten (siehe GNU C Library-Dokumentation ). Der Rest ist einfach Zeichenmanipulation2. Python
Aber auch, weil "warum nicht", hier eine alternative Python-Version über Kommandozeilenargumente
sys.argv
3. Ruby
Ruby wird nicht standardmäßig mit Ubuntu geliefert, im Gegensatz zu C-Compiler und Python-Interpreter. Wenn Sie es jedoch jemals verwenden, lautet die Lösung in Ruby wie folgt:
Wie von 7stud (Vielen Dank!) In den Kommentaren vorgeschlagen , kann dies auch mit gekürzt werden
und so
4. Alternative awk
Wir können die
split()
Funktion verwenden, um die gelesene Zeile in ein Array aufzuteilen, und diefor-each
Schleife verwenden, um jedes Element in einer separaten Zeile auszudrucken.quelle
puts
druckt die Elemente eines Arrays automatisch in separate Zeilen! Sie können auch festlegen, dass die Schalter die Aufteilung durchführen:ruby -F: -ane 'puts $F' <<<$PATH
Erläuterung:-F
Wird$;
auf das angegebene Zeichen festgelegt. Dies ist das von String :: split verwendete Standardtrennzeichen ($; hat den Standardwert nil, der auf Leerzeichen aufgeteilt wird).-a
ruft $ _. split auf, wobei $ _ eine mit gets ()) eingelesene Zeile ist und das resultierende Array zuweist$F
.-F
Flagge gibt - ich fange gerade mit Ruby an und mache die Dinge ein bisschen grob.ruby -0072 -ne 'puts chomp' <<<$PATH
. Erläuterung:-0
Legt das Trennzeichen für Eingabesätze fest (geben Sie ein Zeichen im Oktalformat an; 072 ist ein Doppelpunkt). Ruby verwendet $ _ auf ähnliche Weise wie Perl. Die gets () -Methode (in der-n
Schleife verwendet) setzt $ _ auf die aktuelle Zeile , die eingelesen wird. Undchomp()
ohne ein Argument, chomps $ _. Ich mag deine immer noch besser. :)-F
flag gepostet haben, kürzer. Wenn Sie das tunecho "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c
, heißt das, dass es 271 Bytes sind, aber die mit der Oktalzahl ist 276. Das gilt natürlich für den gesamten Befehl. Wenn wir nur den Code selbst betrachten,puts $F
ist dieser deutlich kürzer. :) Übrigens, kennen Sie Code Golf ? Es ist die Seite für Lösungen zum Programmieren von Rätseln in kürzester Anzahl von Bytes. Es gibt eine Frage zu dieser: codegolf.stackexchange.com/q/96334/55572Wahrscheinlich ist der einzige Weg, der nicht erwähnt wurde, der Weg, den ich seit Jahren benutze:
echo $PATH | tr ":" "\n"
In Ihrem .profile oder .bash_profile oder was auch immer können Sie Folgendes hinzufügen:
alias path='echo $PATH | tr ":" "\n"'
quelle
Wir brauchen mehr Java!
Speichern Sie dies in
GetPathByLine.java
und kompilieren Sie es mit:Laufen mit:
quelle
python3 -c "import os; [print(p) for p in os.getenv('PATH').split(':')]"
Durch awk.
Durch Python.
Beachten Sie, dass Einrückungen in Python sehr wichtig sind.
quelle
echo $PATH | awk '{gsub(/\:/,"\n");print}'
fileinput
wenn Sie nur verwenden könnteninput
:python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
Ich benutze Stephen Collyers "Bash Path Functions" (siehe seinen Artikel im Linux Journal ). Es erlaubt mir, die "durch Doppelpunkte getrennte Liste" als Datentyp in der Shell-Programmierung zu verwenden. Zum Beispiel kann ich eine Liste aller Verzeichnisse im aktuellen Verzeichnis erstellen, indem ich:
Dann
listpath -p dirs
wird eine Liste erstellt.quelle
Erklärung zur @ Cyrus-Antwort
Anmerkungen:
ANSI-C Quoting - erklärt $ 'some \ ntext'
Shell Parameter Expansion - erklärt $ {parameter / pattern / string}. Wenn pattern mit '/' beginnt, werden alle Übereinstimmungen von pattern durch string ersetzt.
Also haben wir:
quelle
Eine andere AWK-Methode besteht darin, jedes Verzeichnis als separaten Datensatz und nicht als separates Feld zu behandeln .
Ich finde diese Syntax besonders intuitiv. Wenn Sie möchten, können Sie es jedoch verkürzen, indem Sie das
print $0
implizite Element festlegen (dies ist die Standardaktion,1
die mit true ausgewertet wird und für jede Zeile ausgeführt wird):Das standardmäßige Eingabe- und Ausgabesatztrennzeichen von AWK ist der Zeilenumbruch. Durch Setzen des Trennzeichens (
RS
) für:
Eingabedatensätze vor dem Lesen der Eingabe analysiert AWK automatisch einen durch Doppelpunkte getrennten Namen$PATH
in den konstituierenden Verzeichnisnamen. AWK wird$0
auf jeden vollständigen Datensatz erweitert, die neue Zeile bleibt das Trennzeichen für den Ausgabedatensatz , und es ist keine Schleifegsub
erforderlich.AWK wird häufig zum Parsen von Datensätzen in separate Felder verwendet, es ist jedoch nicht erforderlich, lediglich eine Liste von Verzeichnisnamen zu erstellen.
Dies funktioniert auch für Eingaben mit Leerzeichen (Leerzeichen und Tabulatoren) und mehreren aufeinanderfolgenden Leerzeichen:
Das heißt, es sei denn, Sie veranlassen AWK , den Datensatz neu zu erstellen (siehe unten), ist es kein Problem, Leerzeichen oder Tabulatoren (die Standardfeldtrennzeichen) in der Eingabe zu haben. Ihr enthält
PATH
wahrscheinlich keine Leerzeichen auf einem Ubuntu-System, aber wenn dies der Fall ist, funktioniert dies immer noch.Es ist erwähnenswert, als eine Randnotiz, dass AWK Fähigkeit eine Aufzeichnung als eine Sammlung von Feldern zu interpretieren wird , die für das damit verbundene Problem der Konstruktion eine Tabelle von Verzeichnis Komponenten :
Die merkwürdige
$1=$1
Aufgabe hat den Zweck, AWK zu zwingen , den Datensatz neu zu erstellen .(Dies ist wahrscheinlich nützlicher für Fälle, in denen zusätzliche Verarbeitung für die Komponenten ausgeführt werden soll, als für das genaue gezeigte Beispiel des einfachen Druckens der Tabelle.)
quelle
quelle
Dies sind meine bevorzugten Methoden, basierend auf meinen jeweiligen Anwendungsfällen und Bedenken hinsichtlich Kompatibilität und Ressourcennutzung.
tr
Wenn Sie eine schnelle, leicht zu merkende und lesbare Lösung benötigen, wiederholen Sie diese und leiten Sie
PATH
sie an translate (tr
) weiter , um die Doppelpunkte in Zeilenumbrüche umzuwandeln:Es hat den Nachteil, dass aufgrund der Pipe zwei Prozesse verwendet werden, aber wenn wir nur in ein Terminal hacken, interessiert uns das wirklich?
Bashs Shell-Parameter-Erweiterung
Wenn Sie eine relativ dauerhafte Lösung
.bashrc
für die interaktive Verwendung wünschen , können Sie den folgenden Befehl als Alias verwendenpath
, die Lesbarkeit dieser Lösung ist jedoch fraglich:Der obige Befehl ersetzt den Doppelpunkt mit Zeilenumbrüchen unter Verwendung der Shell-Parametererweiterung von Bash :
Um es zu erklären:
Viel Glück, wenn Sie sich daran erinnern, wenn Sie nur über die Befehlszeile hacken, wenn Sie es aber nicht geglättet haben.
IFS, getestet in Bash und Dash
Alternativ können Sie die folgende Funktion verwenden, wenn Sie einen ziemlich kompatiblen, lesbaren und verständlichen Ansatz verfolgen, der sich auf nichts anderes als die Shell stützt (ich schlage in Ihrem Beispiel vor
.bashrc
).Die folgende Funktion macht das interne (oder Eingabe-) Feldtrennzeichen (IFS) vorübergehend zu einem Doppelpunkt, und wenn ein Array übergeben wird,
printf
wird es ausgeführt, bis das Array aufgebraucht ist:Diese Methode der Funktion Schöpfung ,
IFS
undprintf
sind für die von Posix vorgesehen, so dass es in den meisten Posix artigen Schalen funktionieren sollte (vor allem Dash, die Ubuntu in der Regel Aliase wiesh
).Python
Solltest du dafür Python verwenden? Du könntest. Dies ist der kürzeste Python-Befehl, den ich mir vorstellen kann:
oder nur Python 3 (und vielleicht besser lesbar?):
Diese sollten auch in jeder normalen Shell-Umgebung funktionieren, solange Sie Python haben.
quelle
Diese Lösung ist einfacher als die Java , C , go und awk- Lösungen:
Hier ist eine weitere großartige Möglichkeit:
Dazu müssten einige Abhängigkeiten installiert werden:
quelle