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}"
Myślę, że to najlepsze rozwiązanie, ponieważ odbywa się to w czystym bashu.
ryanmjacobs
1
@ryanmjacobs lekko ciekawy: jak myślisz, czego używa moje rozwiązanie? : D
muru
1
proszę wyjaśnić, jak to działa.
Tulains Córdova
Jak nazywa się ten rodzaj operacji? Jest podobny do sed, ale nie jest sed. Jak się nazywa, żebym mógł przeszukiwać Internet, by uzyskać więcej informacji na ten temat.
Tulains Córdova
3
Kliknij link (rozszerzenie parametru) w mojej odpowiedzi i przewiń w dół do ostatniej drugiej sekcji o nazwie:${parameter/pattern/string}
Cyrus
27
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.
czy zmiany w tym, na przykład echo $PATH | xargs -n1 -d: echobyłyby zbędne, czy to nie ma znaczenia?
Sergiy Kolodyazhnyy
@Serg 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ę.
souravc,
7
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
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.
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.
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):
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!
Twoje linijki perl one nie są wystarczająco niejasne! Oto wersja gdzie nie ma kodu do przełącznika -e wykonać ponieważ inne przełączniki obsługiwać wszystko: 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.
7stud
Należy również pamiętać, że za pomocą przykładów -Fmożna wyeliminować -ai -nflagi, jak -F włącza te automatycznie: perl -F: -e 'print(join "\n", @F);' <<<$PATH. Zobacz perlrun . Ładne przykłady.
7stud
@ 7stud wow, to naprawdę genialne, dzięki! Bezwstydnie skradziony i dodany do mojej odpowiedzi (zakładam, że ci to nie przeszkadza, nie krępuj się opublikować ją jako odpowiedź, a ja ją usunę). I dzięki za -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.
terdon
Hej dzięki. Jedno wyjaśnienie dotyczące tego stwierdzenia: Na koniec -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.
7stud
Zakładam, że nie masz nic przeciwko - Wcale nie. :)
7stud
6
W tej odpowiedzi:
do
Pyton
Rubin
Alternatywny awk
1. C.
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
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ć
Ładny rubinowy przykład. 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.
7stud
@ 7stud hej, dzięki! :) Nie wiedziałem, że jest -Fflaga - zaczynam od Ruby, więc robię rzeczy nieco prymitywnie.
Sergiy Kolodyazhnyy
Nie, to jest niejasne. Twoja jedna wkładka jest bardzo czytelna, a klarowność powinna za każdym razem przebijać zwięzłość.
7stud
Hah I zorientowali się jeden krótszy: 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. :)
7stud
@ 7stud, ten, który wcześniej opublikowałeś, z -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
Sergiy Kolodyazhnyy
5
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ć:
Nie jestem pewien, dlaczego zawracasz sobie głowę, fileinputkiedy możesz po prostu użyć input:python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
wjandrea
2
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*;doif[-d $i ];then addpath -p dirs $i;fi;done
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:
wzorzec /: zaczynający się od „/”, aby zastąpić wszystkie dopasowania
ciąg $ '\ n', który jest cytowany ze skurczem $ 'anyext', aby traktować nowy symbol linii (\ n).
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.
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
(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).
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.
tr
Po 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?
Rozszerzenie parametrów powłoki Basha
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.
# 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ś.
IFS, przetestowany w Bash i Dash
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).
Pyton
Czy powinieneś do tego użyć Pythona? Mógłbyś. To jest najkrótsza komenda Pythona, o której mogę pomyśleć:
Odpowiedzi:
Spróbuj
sed
:Lub
tr
:Lub
python
:Tutaj wszystkie powyższe zastąpią wszystkie wystąpienia
:
nowymi liniami\n
.źródło
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)tr
pracował 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 :
Wszystko to zastępuje
:
w$PATH
nową linią (\n
) i drukuje wynik. Treść$PATH
pozostaje niezmieniona.Jeśli chcesz tylko zastąpić pierwszy
:
, usuń drugi ukośnik:echo -e "${PATH/:/\n}"
źródło
${parameter/pattern/string}
Korzystanie z IFS:
IFS
zawiera znaki, na których bash dzieli się, więcIFS
z:
powoduje, że bash dzieli rozszerzenie$PATH
na:
.printf
zapę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.źródło
Używanie
xargs
:Od
man xargs
źródło
echo $PATH | xargs -n1 -d: echo
był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 oceniecho $PATH
i przesyła dane wyjściowe do następnej powłoki, aby wykonać resztę.Oto odpowiednik w Go:
źródło
Oto kilka innych podejść. Używam
PATH
z katalogami zawierającymi ukośniki odwrotne, spacje, a nawet nową linię, aby pokazać, że powinny działać ze wszystkim (oprócz tego,cut
który zawodzi na nowych liniach):Niektóre sposoby Perla:
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.-l
Dodaje nowej linii do każdejprint
rozmowy. Tutaj skrypt dzieli swój wkład,:
a następnie zapętla każdy podzielony element i drukuje go.Te
-a
markiperl
zachowują się jakawk
: 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ę spowodujeprint @list
wydrukowanie każdego elementu,@list
a następnie nowej linii. Tutaj używamy go do drukowania@F
.Taki sam pomysł jak powyżej, tylko mniej golfa. Zamiast używać
$"
, jawniejoin
wprowadzamy tablicę z nowymi liniami, a następnie drukujemy.Proste
grep
z magią PCRE:Te
-o
markigrep
wydrukować tylko część dopasowanie każdej linii, więc każdy mecz jest drukowany na oddzielnej linii.-P
Umoż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\K
to sztuczka PCRE, która oznacza „odrzuć wszystko pasujące przed tym punktem” i jest używana tutaj, aby uniknąć drukowania:
również.I
cut
rozwiązanie (to nie działa na nowych liniach, ale może radzić sobie z odwrotnymi ukośnikami i spacjami):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ęccommand <<<"foo"
jest równoważnaecho -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ć:
To się nazywa golf .
-0
Określa separator rekordu wejściowego jako liczby ósemkowej lub szesnastkowej. To właśnie definiuje „linię”, a jej wartością domyślną jest\n
znak nowej linii. Tutaj ustawiamy go na:
co jestx3a
w hex (TRYprintf '\x3a\n'
).-l
Robi 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 (012
jest\n
). Jeśli$\
jest zdefiniowane, jest dodawane na końcu każdegoprint
połączenia, więc spowoduje to dołączenie nowego wiersza do każdegoprint
.-pe
Wola 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!źródło
perl -0x3a -l012 -pe '' <<<$PATH
. Objaśnienie:-0
ustawia separator rekordów wejściowych (określony w notacji szesnastkowej / ósemkowej, x3A jest dwukropkiem),-l
robi 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-p
odciski LOOP OUT wartości $ _, który będzie każdy wiersz przeczytać w.-F
można wyeliminować-a
i-n
flagi, jak -F włącza te automatycznie:perl -F: -e 'print(join "\n", @F);' <<<$PATH
. Zobacz perlrun . Ładne przykłady.-F
informację. Używam w-F
połączeniu z-an
od 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.-l
dodaje 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-l
jus ustawia$/
, a to powoduje, że print dodaje nowy wiersz na końcu łańcucha.W tej odpowiedzi:
1. C.
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 postaciami2. Python
Ale także dlatego, że „dlaczego nie”, oto alternatywna wersja Pythona za pomocą argumentów wiersza poleceń
sys.argv
3. Ruby
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:
Jak sugeruje 7stud (Dziękuję bardzo!) W komentarzach , można to również skrócić
i w ten sposób
4. Alternatywny awk
Możemy użyć
split()
funkcji do rozbicia linii odczytanej na tablicę i użyćfor-each
pętli do wydrukowania każdego elementu w osobnej linii.źródło
puts
automatycznie drukuje elementy tablicy na osobnych liniach! Możesz także ustawić przełączniki na podział:ruby -F: -ane 'puts $F' <<<$PATH
Objaśnienie:-F
ustawia$;
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).-a
wywołuje $ _. split, gdzie $ _ jest linią wczytywaną za pomocą gets ()) i przypisuje wynikową tablicę do$F
.-F
flaga - zaczynam od Ruby, więc robię rzeczy nieco prymitywnie.ruby -0072 -ne 'puts chomp' <<<$PATH
. Objaśnienie:-0
ustawia 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-n
pętli) ustawia $ _ na bieżący wiersz, który jest wczytywany.chomp()
Bez argumentu chomps $ _. Nadal lubię twój. :)-F
flagą, 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 kodputs $F
jest 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/55572Prawdopodobnie 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"'
źródło
Potrzebujemy więcej Java!
Zapisz to
GetPathByLine.java
i skompiluj używając:Biegnij z:
źródło
python3 -c "import os; [print(p) for p in os.getenv('PATH').split(':')]"
Przez awk.
Poprzez python.
Zauważ, że wcięcie jest bardzo ważne w Pythonie.
źródło
echo $PATH | awk '{gsub(/\:/,"\n");print}'
fileinput
kiedy 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:
Następnie
listpath -p dirs
tworzy listę.źródło
Wyjaśnienie dotyczące odpowiedzi @Cyrus
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:
źródło
Innym sposobem AWK jest traktowanie każdego katalogu jako osobnego rekordu , a nie oddzielnego pola .
Uważam tę składnię za szczególnie intuicyjną. Ale jeśli chcesz, możesz go skrócić, czyniąc
print $0
domniemaną (jest to akcja domyślna i1
ocenia na prawdę, co powoduje, że jest wykonywana dla każdej linii):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$PATH
w jego stałych nazwach katalogów. AWK rozwija się$0
do każdego całego rekordu, nowy wiersz pozostaje separatorem rekordów wyjściowych i nie wymaga zapętlania anigsub
jest potrzebny.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:
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
PATH
prawdopodobnie 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 :
Dziwne
$1=$1
zadanie 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).
źródło
źródło
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.
tr
Po pierwsze, jeśli potrzebujesz szybkiego, łatwego do zapamiętania i czytelnego rozwiązania, po prostu wykonaj echo
PATH
i potokuj go, aby tłumaczyć (tr
), aby przekształcić dwukropki w nowe linie: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?
Rozszerzenie parametrów powłoki Basha
Jeśli chcesz mieć dość trwałe rozwiązanie
.bashrc
interaktywne, możesz użyć aliasu następującego poleceniapath
, ale jego czytelność jest wątpliwa:Powyższe polecenie zastępuje dwukropek nowymi liniami przy użyciu rozszerzenia parametrów powłoki Basha :
Aby to wyjaśnić:
Powodzenia, gdy pamiętasz o tym, gdy hakujesz w wierszu poleceń, jeśli jeszcze tego nie zrobiłeś.
IFS, przetestowany w Bash i Dash
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
printf
ona wykonywana, dopóki tablica nie zostanie zużyta:Ta metoda tworzenia funkcji ,
IFS
iprintf
są przewidziane posix, więc powinien działać w większości POSIX jak powłok (zwłaszcza Dash, które instalacyjne? Zwykle aliasamish
).Pyton
Czy powinieneś do tego użyć Pythona? Mógłbyś. To jest najkrótsza komenda Pythona, o której mogę pomyśleć:
lub tylko Python 3 (a może bardziej czytelny?):
Powinny one również działać w każdym zwykłym środowisku powłoki, o ile masz Python.
źródło
To rozwiązanie jest prostsze niż Java , C , go i awk :
Oto kolejna świetna możliwość:
Wymagałoby to zainstalowania niektórych zależności:
źródło