Saya tidak tahu cara membuat daftar berbagai jalur secara $PATH
terpisah sehingga terlihat seperti ini:
/bin
/usr/bin
/usr/local/bin
dll.
Adakah yang tahu variabel yang benar untuk ini?
Saya tidak tahu cara membuat daftar berbagai jalur secara $PATH
terpisah sehingga terlihat seperti ini:
/bin
/usr/bin
/usr/local/bin
dll.
Adakah yang tahu variabel yang benar untuk ini?
Jawaban:
Coba sed
:
$ sed 's/:/\n/g' <<< "$PATH"
Atau tr
:
$ tr ':' '\n' <<< "$PATH"
Atau python
:
$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"
Di sini semua hal di atas akan menggantikan semua kemunculan :
dengan baris baru \n
.
python -c 'import sys;print sys.argv[1].replace(":","\n")' $PATH
python -c "print r'$PATH'.replace(':', '\n')"
(menggunakan string mentah untuk backslash)
tr
bekerja untuk saya (di mac, btw). Terima kasih.
.bash_profile
, tambahkan seperti ini:alias path='tr ":" "\n" <<< "$PATH"'
Gunakan Ekspansi Parameter bash :
echo "${PATH//:/$'\n'}"
Ini menggantikan semua :
dalam $PATH
oleh newline ( \n
) dan mencetak hasilnya. Konten $PATH
tetap tidak berubah.
Jika Anda hanya ingin mengganti yang pertama :
, hapus garis miring kedua:echo -e "${PATH/:/\n}"
${parameter/pattern/string}
Menggunakan IFS:
(set -f; IFS=:; printf "%s\n" $PATH)
IFS
memegang karakter tempat bash melakukan pemisahan, jadi sebuah IFS
dengan :
membuat bash membagi ekspansi $PATH
on :
. printf
loop argumen di atas string format sampai argumen habis. Kita perlu menonaktifkan globbing (ekspansi wildcard) set -f
agar wildcard dalam nama direktori PATH tidak diperluas.
Menggunakan xargs
:
xargs -n1 -d: <<< $PATH
Dari 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: echo
berlebihan atau tidak masalah?
echo $PATH | xargs -n1 -d:
akan melakukan hal yang sama untuk Anda tetapi Anda akan menggunakan satu shell lagi. Yang pertama akan mengevaluasi echo $PATH
dan menyalurkan output ke shell berikutnya untuk melakukan sisanya.
Inilah yang setara di 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
Berikut adalah beberapa pendekatan lagi. Saya menggunakan a PATH
dengan direktori yang berisi garis miring terbalik, spasi dan bahkan baris baru untuk menunjukkan bahwa mereka harus bekerja dengan apa pun (kecuali cut
yang gagal pada baris baru):
$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even
new lines
Beberapa cara Perl:
$ perl -pe 's/:/\n/g' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
The -p
berarti "mencetak setiap baris masukan setelah menerapkan script yang diberikan oleh -e
". Skrip menggunakan operator substitusi ( s/oldnew/
) untuk mengganti semua :
dengan baris baru.
$ perl -lne 'print for split /:/' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
The -l
menambahkan baris baru untuk setiap print
panggilan. Di sini, skrip membagi inputnya :
dan kemudian mengulangi setiap elemen yang terpecah dan mencetaknya.
$ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
The -a
merek perl
berperilaku seperti awk
: itu akan membagi masing-masing jalur input pada karakter yang diberikan oleh -F
(jadi :
, di sini) dan menyimpan hasilnya dalam array @F
. Ini $"
adalah variabel Perl khusus, "pemisah daftar", yang nilainya dicetak di antara setiap elemen daftar yang dicetak. Jadi pengaturannya ke baris baru akan membuat print @list
mencetak setiap elemen @list
dan kemudian baris baru. Di sini, kami menggunakannya untuk mencetak @F
.
$ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Gagasan yang sama seperti di atas, hanya kurang golf. Alih-alih menggunakan $"
, kami secara eksplisit join
menggunakan array dengan baris baru dan kemudian mencetak.
Sederhana grep
dengan sihir PCRE:
$ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
The -o
merek grep
mencetak hanya bagian pencocokan setiap baris, sehingga setiap pertandingan dicetak pada baris terpisah. Yang -P
memungkinkan Perl Kompatibel Regular Expressions (PCRE). Regex mencari rentang non- :
( [^:]+
) yang mengikuti awal baris ( ^
) atau :
karakter. Ini \K
adalah trik PCRE yang berarti "membuang apa pun yang cocok sebelum titik ini" dan digunakan di sini untuk menghindari pencetakan :
juga.
Dan cut
solusinya (yang ini gagal pada baris baru, tetapi bisa berurusan dengan garis miring terbalik dan spasi):
$ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Opsi yang digunakan adalah -d:
yang mengatur pembatas input :
, -f 1-
yang berarti mencetak semua bidang (dari tanggal 1 hingga akhir) dan --output-delimiter=$'\n'
yang menetapkan pembatas keluaran, baik,. The $'\n'
adalah ANSI C mengutip dan merupakan cara untuk mencetak karakter baris baru di shell.
Dalam semua contoh di atas, saya menggunakan operator string ( <<<
) di bash's (dan beberapa shells lainnya ) untuk meneruskan string sebagai input ke sebuah program. Jadi command <<<"foo"
setara dengan echo -n "foo" | command
. Perhatikan bahwa saya selalu mengutip "$PATH"
, tanpa tanda kutip, shell akan memakan karakter baris baru.
@ 7stud memberikan pendekatan lain dalam komentar yang terlalu bagus untuk tidak menyertakan:
$ perl -0x3a -l012 -pe '' <<<"$PATH"
Itulah yang dikenal sebagai golf . The -0
menetapkan rekor pemisah masukan sebagai bilangan oktal atau heksadesimal. Inilah yang mendefinisikan "garis" dan nilai defaultnya adalah \n
, karakter baris baru. Di sini, kita sedang menyiapkan itu untuk :
yang x3a
di hex (try printf '\x3a\n'
). Ada -l
tiga hal. Pertama menghilangkan pemisah record input ( $/
) dari akhir setiap baris-efektif menghapus :
sini-dan kedua, ia menetapkan pemisah record keluaran ( $\
) untuk apa pun yang oktal atau nilai hex itu diberikan ( 012
adalah \n
). Jika $\
ditentukan, ditambahkan ke akhir setiap print
panggilan, sehingga ini akan menghasilkan baris baru yang ditambahkan ke masing-masing print
.
The -pe
kehendak p etak setiap baris masukan setelah menerapkan script yang diberikan oleh -e
. Di sini tidak ada skrip karena semua pekerjaan dilakukan oleh flag opsi seperti yang dijelaskan di atas!
perl -0x3a -l012 -pe '' <<<$PATH
. Penjelasan: -0
mengatur pemisah rekaman input (ditentukan dalam notasi heks / oktal, x3A adalah titik dua), -l
melakukan dua hal: 1) mengompol pemisah catatan input, 2) mengatur pemisah catatan keluaran jika ditentukan, (dalam notasi oktal) , 012 adalah baris baru). Sebuah -p
loop mencetak nilai $ _, yang akan menjadi setiap baris yang dibaca.
-F
informasinya. Saya telah menggunakan -F
dikombinasikan dengan -an
selama bertahun-tahun, saya tidak pernah menyadari yang tersirat yang lain. Ngomong-ngomong, saya melihat Serg menyebutkan Code Golf , tapi saya pikir Anda juga akan menikmati Unix & Linux jika Anda menyukai hal seperti ini.
-l
juga menambahkan pemisah catatan keluaran yang diberikan pada akhir setiap panggilan cetak. Bahkan, cetak selalu menambahkan pemisah catatan keluaran $/
,, ke akhir string - jika pemisah catatan keluaran ditentukan. Secara default itu adalah undef. Jadi hanya -l
set $/
, dan itu menyebabkan cetakan menambahkan baris baru ke akhir string.
Karena semua bahasa skrip telah diambil, saya akan menggunakan C. Sangat mudah untuk mendapatkan variabel lingkungan dengan get_env()
fungsi (lihat dokumentasi Perpustakaan C GNU ). Sisanya hanyalah manipulasi karakter
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
Tetapi juga karena "mengapa tidak", inilah versi python alternatif melalui argumen baris perintah sys.argv
python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"
Ruby tidak datang dengan Ubuntu secara default, tidak seperti C compiler dan Python interpreter, tetapi jika Anda pernah menggunakannya, solusi di Ruby adalah sebagai berikut:
ruby -ne 'puts $_.split(":")' <<< "$PATH"
Seperti yang disarankan oleh 7stud (Terima kasih banyak!) Di komentar , ini juga dapat disingkat
ruby -F: -ane 'puts $F' <<<$PATH
dan dengan cara ini
ruby -0072 -ne 'puts chomp' <<<$PATH
Kita dapat menggunakan split()
fungsi untuk memecah baris yang dibaca menjadi array, dan menggunakan for-each
loop untuk mencetak setiap item pada baris yang terpisah.
awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
puts
secara otomatis mencetak elemen-elemen array pada baris yang berbeda! Anda juga dapat membuat sakelar melakukan pemisahan: ruby -F: -ane 'puts $F' <<<$PATH
Penjelasan: -F
menetapkan $;
ke karakter yang ditentukan, yang merupakan pemisah default yang digunakan oleh String :: split ($; memiliki nilai default nil, yang terbagi pada spasi putih). -a
panggilan $ _. split, di mana $ _ adalah baris yang dibaca menggunakan gets ()) dan menetapkan array yang dihasilkan $F
.
-F
flag - Saya baru memulai dengan Ruby, jadi melakukan hal-hal dengan cara yang agak kasar.
ruby -0072 -ne 'puts chomp' <<<$PATH
. Penjelasan: -0
mengatur pemisah rekaman input (tentukan karakter dalam format oktal; 072 adalah titik dua). Ruby menggunakan $ _ dengan cara yang mirip dengan Perl. Metode gets () (digunakan dalam -n
loop) menetapkan $ _ ke baris saat ini yang dibaca. Dan chomp()
tanpa arg, chomps $ _. Aku masih lebih suka milikmu. :)
-F
bendera, lebih pendek. Jika Anda melakukan echo "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c
itu memberitahu saya itu 271, byte, tetapi yang dengan angka oktal adalah 276. Itu untuk seluruh perintah, tentu saja, Jika kita menganggap hanya kode itu sendiri puts $F
jelas lebih pendek. :) Ngomong-ngomong, apakah Anda tahu tentang Code Golf ? Ini adalah situs untuk solusi teka-teki pemrograman dalam jumlah byte terpendek. Ada pertanyaan terkait dengan ini: codegolf.stackexchange.com/q/96334/55572
Mungkin satu-satunya cara yang belum disebutkan adalah cara saya menggunakannya selama bertahun-tahun:
echo $PATH | tr ":" "\n"
jadi, di .profile atau .bash_profile Anda atau apa pun, Anda dapat menambahkan:
alias path='echo $PATH | tr ":" "\n"'
Kami membutuhkan lebih banyak Jawa!
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
Simpan ini untuk GetPathByLine.java
, dan kompilasi menggunakan:
javac GetPathByLine.java
Jalankan dengan:
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(':')]"
Melalui awk.
echo $PATH | awk -F: '{for(i=1;i<=NF;i++)print $i}'
Melalui python.
$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
for i in line.split(":"):
print(i)'
Perhatikan bahwa Indentasi sangat penting dalam python.
echo $PATH | awk '{gsub(/\:/,"\n");print}'
fileinput
ketika Anda bisa menggunakan input
:python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
Saya menggunakan "Fungsi Bash Path" Stephen Collyer (lihat artikelnya di Linux Journal ). Ini memungkinkan saya untuk menggunakan "daftar terpisah usus" sebagai datatype dalam pemrograman shell. Sebagai contoh, saya dapat menghasilkan daftar semua direktori di direktori saat ini dengan:
dirs="";for i in * ; do if [ -d $i ] ; then addpath -p dirs $i; fi; done
Kemudian, listpath -p dirs
buat daftar.
Penjelasan untuk jawaban @Cyrus
echo "${PATH//:/$'\n'}"
Catatan:
ANSI-C Quoting - menjelaskan $ 'some \ ntext'
Ekspansi Parameter Shell - menjelaskan $ {parameter / pattern / string}, Jika pola dimulai dengan '/', semua kecocokan pola diganti dengan string.
Jadi kita punya:
Cara AWK lainnya adalah memperlakukan setiap direktori sebagai catatan terpisah , bukan sebagai bidang terpisah .
awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
Saya menemukan bahwa sintaks sangat intuitif. Tetapi, jika Anda suka, Anda dapat mempersingkatnya dengan membuat yang print $0
tersirat (itu adalah tindakan default, dan 1
mengevaluasi menjadi true, menyebabkannya dilakukan untuk setiap baris):
awk 'BEGIN{RS=":"} 1' <<<"$PATH"
Input default dan pemisah catatan keluaran AWK adalah baris baru (line break). Dengan mengatur pemisah rekaman input ( RS
) ke :
sebelum membaca input, AWK secara otomatis mem-parsing sebuah usus yang dipisahkan $PATH
menjadi nama direktori konstituennya. AWK mengembang $0
ke setiap keseluruhan rekaman, baris baru tetap menjadi pemisah rekaman keluaran , dan tidak perlu perulangan atau gsub
diperlukan.
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 sering digunakan untuk mem-parsing catatan ke bidang yang terpisah, tetapi tidak perlu untuk itu hanya untuk membangun daftar nama direktori.
Ini berfungsi bahkan untuk input yang berisi kosong (spasi dan tab), bahkan beberapa kosong berturut-turut:
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<$'ab\t\t c:de fg:h'
ab c
de fg
h
Artinya, kecuali Anda menyebabkan AWK untuk membangun kembali catatan (lihat di bawah), tidak ada masalah untuk memiliki spasi atau tab (pemisah bidang default) di input. Anda PATH
mungkin tidak mengandung spasi pada sistem Ubuntu, tetapi jika itu, ini masih berfungsi.
Perlu disebutkan, sebagai catatan, bahwa kemampuan AWK untuk menafsirkan catatan sebagai kumpulan bidang menjadi berguna untuk masalah terkait membangun tabel komponen direktori :
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
Tugas penasaran $1=$1
melayani tujuan memaksa AWK untuk membangun kembali catatan .
(Ini mungkin lebih berguna untuk kasus-kasus di mana pemrosesan tambahan harus dilakukan pada komponen, daripada untuk contoh yang tepat ditampilkan hanya dengan mencetak tabel.)
jq -Rr 'gsub(":";"\n")' <<<$PATH
Cara menampilkan path di $ PATH secara terpisah
Ini adalah cara yang saya sukai untuk melakukan ini berdasarkan kasus penggunaan saya masing-masing dan masalah tentang kompatibilitas dan penggunaan sumber daya.
tr
Pertama, jika Anda membutuhkan solusi yang cepat, mudah diingat, dan mudah dibaca, cukup gema PATH
dan pipa untuk menerjemahkan ( tr
) untuk mengubah titik dua menjadi baris baru:
echo $PATH | tr : "\n"
Kelemahan dari menggunakan dua proses karena pipa, tetapi jika kita hanya meretas terminal, apakah kita benar-benar peduli tentang itu?
Jika Anda menginginkan solusi yang cukup permanen .bashrc
untuk penggunaan interaktif, Anda dapat alias menjalankan perintah berikut path
, tetapi keterbacaan solusi ini dipertanyakan:
alias path="echo \"${PATH//:/$'\n'}\""
Jika pola dimulai dengan '/', semua kecocokan pola diganti dengan string. Biasanya hanya pertandingan pertama yang diganti.
Perintah di atas menggantikan titik dua dengan baris baru menggunakan Ekspansi Parameter Shell Bash :
${parameter/pattern/string}
Untuk menjelaskannya:
# v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"
# ^^ ^^^^^----string, $ required to get newline character.
# \----------pattern, / required to substitute for *every* :.
Semoga beruntung mengingat ini ketika Anda baru saja meretas pada baris perintah, jika Anda belum alias.
Atau, pendekatan yang cukup kompatibel lintas, dapat dibaca, dan dimengerti yang tidak bergantung pada apa pun selain shell menggunakan fungsi berikut (saya sarankan di Anda .bashrc
.)
Fungsi berikut untuk sementara membuat Pemisah Lapangan (IFS) Internal (atau Input) sebuah titik dua, dan ketika sebuah array diberikan printf
, ia dijalankan sampai array habis:
path () {
local IFS=:
printf "%s\n" ${PATH}
}
Metode pembuatan fungsi , IFS
dan printf
disediakan oleh POSIX, sehingga harus bekerja di sebagian besar POSIX-seperti kerang (terutama Dash, yang Ubuntu biasanya alias sebagaish
).
Haruskah Anda menggunakan Python untuk ini? Anda bisa. Ini adalah perintah Python terpendek yang dapat saya pikirkan untuk ini:
python -c "print('\n'.join('${PATH}'.split(':')))"
atau hanya Python 3 (dan mungkin lebih mudah dibaca?):
python3 -c "print(*'${PATH}'.split(':'), sep='\n')"
Ini harus bekerja di lingkungan shell biasa juga, selama Anda memiliki Python.
Solusi ini lebih sederhana daripada solusi Java , C , go and awk :
$ LPATH=$PATH wine cmd /c echo %LPATH::=$'\n'% 2> /dev/null
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
Berikut kemungkinan besar lainnya:
$ 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
Ini akan membutuhkan beberapa dependensi untuk diinstal:
sudo apt-get install openjdk-8-jdk-headless bsh