Nie mogę wymyślić, jak wymienić poszczególne ścieżki $PATHosobno, aby wyglądały tak:
/bin
/usr/bin
/usr/local/bin
itp.
Czy ktoś zna poprawną zmienną do tego?
Nie mogę wymyślić, jak wymienić poszczególne ścieżki $PATHosobno, aby wyglądały tak:
/bin
/usr/bin
/usr/local/bin
itp.
Czy ktoś zna poprawną zmienną do tego?
Odpowiedzi:
Spróbuj sed:
$ sed 's/:/\n/g' <<< "$PATH"
Lub tr:
$ tr ':' '\n' <<< "$PATH"
Lub python:
$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"
Tutaj wszystkie powyższe zastąpią wszystkie wystąpienia :nowymi liniami \n.
python -c 'import sys;print sys.argv[1].replace(":","\n")' $PATH
python -c "print r'$PATH'.replace(':', '\n')"(stosując surowe ciąg w przypadku ukośniki)
trpracował dla mnie (na Mac, BTW). Dzięki.
.bash_profile, dodaj to w ten sposób:alias path='tr ":" "\n" <<< "$PATH"'
Użyj rozszerzenia parametrów bash :
echo "${PATH//:/$'\n'}"
Wszystko to zastępuje :w $PATHnową linią ( \n) i drukuje wynik. Treść $PATHpozostaje niezmieniona.
Jeśli chcesz tylko zastąpić pierwszy :, usuń drugi ukośnik:echo -e "${PATH/:/\n}"
${parameter/pattern/string}
Korzystanie z IFS:
(set -f; IFS=:; printf "%s\n" $PATH)
IFSzawiera znaki, na których bash dzieli się, więc IFSz :powoduje, że bash dzieli rozszerzenie $PATHna :. printfzapętla argumenty nad ciągiem formatu, aż argumenty zostaną wyczerpane. Musimy wyłączyć globbing (rozwijanie symboli wieloznacznych) za pomocą set -f, aby symbole wieloznaczne w nazwach katalogów PATH nie były rozwijane.
Używanie xargs:
xargs -n1 -d: <<< $PATH
Od man xargs
-n max-args
Use at most max-args arguments per command line.
-d delim
Input items are terminated by the specified character.
echo $PATH | xargs -n1 -d: echobyłyby zbędne, czy to nie ma znaczenia?
echo $PATH | xargs -n1 -d: zrobi to samo dla ciebie, ale będziesz używał jeszcze jednej powłoki. Pierwszy oceni echo $PATHi przesyła dane wyjściowe do następnej powłoki, aby wykonać resztę.
Oto odpowiednik w 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
Oto kilka innych podejść. Używam PATHz katalogami zawierającymi ukośniki odwrotne, spacje, a nawet nową linię, aby pokazać, że powinny działać ze wszystkim (oprócz tego, cutktóry zawodzi na nowych liniach):
$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even
new lines
Niektóre sposoby Perla:
$ perl -pe 's/:/\n/g' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Te -pśrodki „wydrukować każdą linię wejściowego po zastosowaniu skryptu podane przez -e”. Skrypt używa operatora podstawienia ( s/oldnew/) do zastąpienia wszystkich :znakami nowej linii.
$ perl -lne 'print for split /:/' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-lDodaje nowej linii do każdej printrozmowy. Tutaj skrypt dzieli swój wkład, :a następnie zapętla każdy podzielony element i drukuje go.
$ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Te -amarki perlzachowują się jak awk: będzie podzielić każdy z jego linii wejściowych od charakteru danej przez -F(tak :, tutaj) i zapisać wynik w tablicy @F. $"Jest specjalną zmienną Perl, „Wykaz separatora”, którego wartość jest drukowany pomiędzy poszczególnymi elementami listy drukowanej. Tak więc ustawienie go na nową linię spowoduje print @listwydrukowanie każdego elementu, @lista następnie nowej linii. Tutaj używamy go do drukowania @F.
$ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Taki sam pomysł jak powyżej, tylko mniej golfa. Zamiast używać $", jawnie joinwprowadzamy tablicę z nowymi liniami, a następnie drukujemy.
Proste grepz magią PCRE:
$ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Te -omarki grepwydrukować tylko część dopasowanie każdej linii, więc każdy mecz jest drukowany na oddzielnej linii. -PUmożliwia pcre (pcre). Wyrażenie regularne szuka ciągów znaków innych niż :( [^:]+), które następują na początku wiersza ( ^) lub :znaku. Jest \Kto sztuczka PCRE, która oznacza „odrzuć wszystko pasujące przed tym punktem” i jest używana tutaj, aby uniknąć drukowania :również.
I cutrozwiązanie (to nie działa na nowych liniach, ale może radzić sobie z odwrotnymi ukośnikami i spacjami):
$ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Zastosowano następujące opcje, -d:które ustawiają ogranicznik wejściowy na :, -f 1-co oznacza drukowanie wszystkich pól (od 1 do końca) i --output-delimiter=$'\n'które ustawiają, no cóż, ogranicznik wyjściowy. Jest $'\n'to cytat ANSI C i jest sposobem na wydrukowanie znaku nowej linii w powłoce.
We wszystkich powyższych przykładach używam tutaj<<< operatora string ( ) bash (i niektórych innych powłok ), aby przekazać ciąg znaków jako dane wejściowe do programu. Więc command <<<"foo"jest równoważna echo -n "foo" | command. Zauważ, że zawsze cytuję "$PATH", bez cytatów, skorupa zjadłaby znak nowej linii.
@ 7stud podał inne podejście w komentarzach, które jest po prostu zbyt dobre, aby nie zawierać:
$ perl -0x3a -l012 -pe '' <<<"$PATH"
To się nazywa golf . -0Określa separator rekordu wejściowego jako liczby ósemkowej lub szesnastkowej. To właśnie definiuje „linię”, a jej wartością domyślną jest \nznak nowej linii. Tutaj ustawiamy go na :co jest x3aw hex (TRY printf '\x3a\n'). -lRobi trzy rzeczy. Najpierw usuwa się separator rekordu wejściowego ( $/) z końca każdej linii, skutecznie usuwając :tutaj, a po drugie, to ustawia separator rekordów wyjściowych ( $\), aby cokolwiek ósemkowe lub wartość hex jest przekazywana ( 012jest \n). Jeśli $\jest zdefiniowane, jest dodawane na końcu każdego printpołączenia, więc spowoduje to dołączenie nowego wiersza do każdego print.
-peWola p rukuj każdą linię wejściowego po zastosowaniu skryptu podane przez -e. Tutaj nie ma skryptu, ponieważ cała praca jest wykonywana przez flagi opcji, jak opisano powyżej!
perl -0x3a -l012 -pe '' <<<$PATH. Objaśnienie: -0ustawia separator rekordów wejściowych (określony w notacji szesnastkowej / ósemkowej, x3A jest dwukropkiem), -lrobi dwie rzeczy: 1) przecina separator rekordów wejściowych, 2) ustawia separator rekordów wyjściowych, jeśli jest określony (w notacji ósemkowej , 012 to nowa linia). A -podciski LOOP OUT wartości $ _, który będzie każdy wiersz przeczytać w.
-Finformację. Używam w -Fpołączeniu z -anod lat, nigdy nie zdawałem sobie sprawy, że ten sugeruje inne. Nawiasem mówiąc, widziałem, jak Serg wspomniał o Code Golf , ale myślę, że spodoba ci się także Unix i Linux, jeśli lubisz takie rzeczy.
-ldodaje również separator rekordów wyjściowych podany na końcu każdego wywołania drukowania. W rzeczywistości print zawsze dodaje separator rekordu wyjściowego $/, na końcu łańcucha - jeśli separator rekordu wyjściowego jest zdefiniowany. Domyślnie jest undef. Więc -ljus ustawia $/, a to powoduje, że print dodaje nowy wiersz na końcu łańcucha.
Ponieważ wszystkie języki skryptowe są już zajęte, wybiorę C. Używanie funkcji jest dość łatwe get_env()(patrz dokumentacja biblioteki GNU C ). Reszta to po prostu manipulacja postaciami
bash-4.3$ cat get_path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *path = getenv("PATH");
int length = strlen(path) -1;
for(int i=0;i<=length;i++){
if (path[i] == ':')
path[i] = '\n';
printf("%c",path[i]);
}
printf("\n");
return 0;
}
bash-4.3$ gcc get_path.c
bash-4.3$ ./a.out
/home/xieerqi/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/opt/microchip/xc16/v1.25/bin
/opt/microchip/xc32/v1.40/bin
/opt/microchip/xc8/v1.35/bin
/home/xieerqi/bin
/home/xieerqi/bin/sh
Ale także dlatego, że „dlaczego nie”, oto alternatywna wersja Pythona za pomocą argumentów wiersza poleceń sys.argv
python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"
Ruby nie jest domyślnie wyposażony w Ubuntu, w przeciwieństwie do kompilatora C i interpretera Pythona, ale jeśli kiedykolwiek go użyjesz, rozwiązaniem w Ruby byłoby:
ruby -ne 'puts $_.split(":")' <<< "$PATH"
Jak sugeruje 7stud (Dziękuję bardzo!) W komentarzach , można to również skrócić
ruby -F: -ane 'puts $F' <<<$PATH
i w ten sposób
ruby -0072 -ne 'puts chomp' <<<$PATH
Możemy użyć split()funkcji do rozbicia linii odczytanej na tablicę i użyć for-eachpętli do wydrukowania każdego elementu w osobnej linii.
awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
putsautomatycznie drukuje elementy tablicy na osobnych liniach! Możesz także ustawić przełączniki na podział: ruby -F: -ane 'puts $F' <<<$PATH Objaśnienie: -Fustawia $;na określony znak, który jest domyślnym separatorem używanym przez String :: split ($; ma domyślną wartość zero, która dzieli się na białe znaki). -awywołuje $ _. split, gdzie $ _ jest linią wczytywaną za pomocą gets ()) i przypisuje wynikową tablicę do $F.
-Fflaga - zaczynam od Ruby, więc robię rzeczy nieco prymitywnie.
ruby -0072 -ne 'puts chomp' <<<$PATH. Objaśnienie: -0ustawia separator rekordów wejściowych (określ znak w formacie ósemkowym; 072 to dwukropek). Ruby zatrudnia $ _ w sposób podobny do Perla. Metoda gets () (używana w -npętli) ustawia $ _ na bieżący wiersz, który jest wczytywany. chomp()Bez argumentu chomps $ _. Nadal lubię twój. :)
-Fflagą, jest krótszy. Jeśli to zrobisz, echo "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c to powie mi, że to 271 bajtów, ale ten z liczbą ósemkową to 276. To oczywiście dotyczy całego polecenia, jeśli weźmiemy pod uwagę, że sam kod puts $Fjest wyraźnie krótszy. :) Przy okazji, czy wiesz o Code Golf ? Jest to strona z rozwiązaniami do programowania łamigłówek w jak najkrótszej liczbie bajtów. Jest z tym związane pytanie: codegolf.stackexchange.com/q/96334/55572
Prawdopodobnie jedynym sposobem, o którym nie wspomniano, jest sposób, w jaki używam go od lat:
echo $PATH | tr ":" "\n"
więc w swoim .profile lub .bash_profile lub czymkolwiek możesz dodać:
alias path='echo $PATH | tr ":" "\n"'
Potrzebujemy więcej Java!
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
Zapisz to GetPathByLine.javai skompiluj używając:
javac GetPathByLine.java
Biegnij z:
java GetPathByLine
┌─[17:06:55]─[kazwolfe@BlackHawk]
└──> ~ $ cat GetPathByLine.java
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
┌─[17:06:58]─[kazwolfe@BlackHawk]
└──> ~ $ javac GetPathByLine.java
┌─[17:07:02]─[kazwolfe@BlackHawk]
└──> ~ $ java GetPathByLine
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
python3 -c "import os; [print(p) for p in os.getenv('PATH').split(':')]"
Przez awk.
echo $PATH | awk -F: '{for(i=1;i<=NF;i++)print $i}'
Poprzez python.
$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
for i in line.split(":"):
print(i)'
Zauważ, że wcięcie jest bardzo ważne w Pythonie.
echo $PATH | awk '{gsub(/\:/,"\n");print}'
fileinputkiedy możesz po prostu użyć input:python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
Używam „Bash Path Functions” Stephena Collyera (zobacz jego artykuł w Linux Journal ). Pozwala mi to na użycie „listy oddzielonych dwukropkami” jako typu danych w programowaniu powłoki. Na przykład mogę utworzyć listę wszystkich katalogów w bieżącym katalogu, wykonując:
dirs="";for i in * ; do if [ -d $i ] ; then addpath -p dirs $i; fi; done
Następnie listpath -p dirstworzy listę.
Wyjaśnienie dotyczące odpowiedzi @Cyrus
echo "${PATH//:/$'\n'}"
Uwagi:
Cytowanie ANSI-C - wyjaśnia $ 'some \ ntext'
Rozszerzenie parametru powłoki - wyjaśnia $ {parametr / wzór / ciąg}, Jeśli wzorzec zaczyna się od „/”, wszystkie dopasowania wzorca są zastępowane ciągiem.
Więc mamy:
Innym sposobem AWK jest traktowanie każdego katalogu jako osobnego rekordu , a nie oddzielnego pola .
awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
Uważam tę składnię za szczególnie intuicyjną. Ale jeśli chcesz, możesz go skrócić, czyniąc print $0domniemaną (jest to akcja domyślna i 1ocenia na prawdę, co powoduje, że jest wykonywana dla każdej linii):
awk 'BEGIN{RS=":"} 1' <<<"$PATH"
Domyślnym separatorem rekordów wejściowych i wyjściowych AWK jest nowa linia (podział wiersza). Ustawiając separator rekordów wejściowych ( RS) na :przed odczytem danych wejściowych, AWK automatycznie analizuje separator dwukropka $PATHw jego stałych nazwach katalogów. AWK rozwija się $0do każdego całego rekordu, nowy wiersz pozostaje separatorem rekordów wyjściowych i nie wymaga zapętlania ani gsubjest potrzebny.
ek@Io:~$ echo "$PATH"
/home/ek/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
ek@Io:~$ awk 'BEGIN{RS=":"} {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
AWK jest często używany do parsowania rekordów w oddzielnych polach, ale nie ma takiej potrzeby, aby zbudować listę nazw katalogów.
Działa to nawet w przypadku danych wejściowych zawierających spacje (spacje i tabulatory), a nawet wielu kolejnych spacji:
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<$'ab\t\t c:de fg:h'
ab c
de fg
h
Oznacza to, że jeśli nie spowoduje to odbudowania rekordu przez AWK (patrz poniżej), nie ma problemu z wprowadzaniem spacji lub tabulatorów (domyślnych separatorów pól) na wejściu. Twój PATHprawdopodobnie nie zawiera spacji w systemie Ubuntu, ale jeśli tak, nadal będzie działać.
Na marginesie warto wspomnieć, że zdolność AWK do interpretowania rekordu jako zbioru pól staje się przydatna w powiązanym problemie tworzenia tabeli składników katalogu :
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
Dziwne $1=$1zadanie ma na celu zmuszenie AWK do odbudowania rekordu .
(Jest to prawdopodobnie bardziej przydatne w przypadkach, w których należy wykonać dodatkowe przetwarzanie komponentów, niż w dokładnym pokazanym przykładzie po prostu wydrukowania tabeli).
jq -Rr 'gsub(":";"\n")' <<<$PATH
Jak wyświetlać ścieżki w $ PATH osobno
Są to moje preferowane sposoby robienia tego w oparciu o moje odpowiednie przypadki użycia i obawy dotyczące zgodności i wykorzystania zasobów.
trPo pierwsze, jeśli potrzebujesz szybkiego, łatwego do zapamiętania i czytelnego rozwiązania, po prostu wykonaj echo PATHi potokuj go, aby tłumaczyć ( tr), aby przekształcić dwukropki w nowe linie:
echo $PATH | tr : "\n"
Ma to tę wadę, że używa dwóch procesów z powodu potoku, ale jeśli po prostu hakujemy terminal, czy naprawdę nas to obchodzi?
Jeśli chcesz mieć dość trwałe rozwiązanie .bashrcinteraktywne, możesz użyć aliasu następującego polecenia path, ale jego czytelność jest wątpliwa:
alias path="echo \"${PATH//:/$'\n'}\""
Jeśli wzorzec zaczyna się od „/”, wszystkie dopasowania wzorca są zastępowane ciągiem. Zwykle tylko pierwszy mecz jest zastępowany.
Powyższe polecenie zastępuje dwukropek nowymi liniami przy użyciu rozszerzenia parametrów powłoki Basha :
${parameter/pattern/string}
Aby to wyjaśnić:
# v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"
# ^^ ^^^^^----string, $ required to get newline character.
# \----------pattern, / required to substitute for *every* :.
Powodzenia, gdy pamiętasz o tym, gdy hakujesz w wierszu poleceń, jeśli jeszcze tego nie zrobiłeś.
Alternatywnie, dość kompatybilne, czytelne i zrozumiałe podejście, które nie opiera się na niczym innym niż powłoka, to skorzystaj z następującej funkcji (sugeruję w twoim .bashrc.)
Poniższa funkcja tymczasowo przekształca wewnętrzny (lub wejściowy) separator pól w dwukropek, a gdy podana jest tablica, jest printfona wykonywana, dopóki tablica nie zostanie zużyta:
path () {
local IFS=:
printf "%s\n" ${PATH}
}
Ta metoda tworzenia funkcji , IFSi printfsą przewidziane posix, więc powinien działać w większości POSIX jak powłok (zwłaszcza Dash, które instalacyjne? Zwykle aliasami sh).
Czy powinieneś do tego użyć Pythona? Mógłbyś. To jest najkrótsza komenda Pythona, o której mogę pomyśleć:
python -c "print('\n'.join('${PATH}'.split(':')))"
lub tylko Python 3 (a może bardziej czytelny?):
python3 -c "print(*'${PATH}'.split(':'), sep='\n')"
Powinny one również działać w każdym zwykłym środowisku powłoki, o ile masz Python.
To rozwiązanie jest prostsze niż Java , C , go i awk :
$ LPATH=$PATH wine cmd /c echo %LPATH::=$'\n'% 2> /dev/null
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
Oto kolejna świetna możliwość:
$ jrunscript -classpath /usr/share/java/bsh.jar -e 'print(java.lang.System.getenv("PATH").replaceAll(":","\n"))'
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
Wymagałoby to zainstalowania niektórych zależności:
sudo apt-get install openjdk-8-jdk-headless bsh