Farklı yolları, $PATH
şöyle görünecek şekilde ayrı ayrı nasıl sıralayacağımı bulamıyorum :
/bin
/usr/bin
/usr/local/bin
vb.
Bunun için doğru değişkeni bilen var mı?
Farklı yolları, $PATH
şöyle görünecek şekilde ayrı ayrı nasıl sıralayacağımı bulamıyorum :
/bin
/usr/bin
/usr/local/bin
vb.
Bunun için doğru değişkeni bilen var mı?
Yanıtlar:
Deneyin sed
:
$ sed 's/:/\n/g' <<< "$PATH"
Veya tr
:
$ tr ':' '\n' <<< "$PATH"
Veya python
:
$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"
Burada, yukarıdakilerin tümü, tüm oluşumlarını :
yeni satırlarla değiştirir \n
.
python -c 'import sys;print sys.argv[1].replace(":","\n")' $PATH
python -c "print r'$PATH'.replace(':', '\n')"
(ters eğik çizgi durumunda ham bir dize kullanarak)
tr
benim için çalıştı (mac, btw). Teşekkürler.
.bash_profile
ekleyin:alias path='tr ":" "\n" <<< "$PATH"'
Bash Parametre Genişletme kullanın :
echo "${PATH//:/$'\n'}"
Bu cümledeki bütün :
içinde $PATH
yeni satır (tarafından \n
) ve baskılar sonucu. $PATH
Kalıntıların içeriği değişmeden kalır.
Yalnızca ilkini değiştirmek istiyorsanız :
, ikinci eğik çizgiyi kaldırın:echo -e "${PATH/:/\n}"
${parameter/pattern/string}
IFS'yi kullanma:
(set -f; IFS=:; printf "%s\n" $PATH)
IFS
Bir nedenle, bash bölme yapar hangi karakterleri tutar IFS
ile :
markaların genişleme bölmek bash $PATH
üzerinde :
. printf
Argümanları tükenene kadar argümanları biçim dizgisinin üzerinden geçirir. set -f
PATH dizin adlarındaki joker karakterlerin genişletilmemesi için globbing'i (joker karakter genişletme) devre dışı bırakmamız gerekiyor.
Kullanarak xargs
:
xargs -n1 -d: <<< $PATH
itibaren 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
varlıklar gereksiz mi yoksa önemi yok mu?
echo $PATH | xargs -n1 -d:
sizin için aynı şeyi yapacak, ancak bir tane daha kabuk kullanacaksınız. Birincisi echo $PATH
, geri kalanını yapmak için çıktıyı değerlendirecek ve bir sonraki kabuğa geçirecektir .
İşte Go'daki karşılığı:
$ 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
İşte birkaç yaklaşım daha. Bir PATH
ters eğik çizgi, boşluk ve hatta herhangi bir şeyle çalışması gerektiğini göstermek için yeni bir satır içeren bir dizini kullanıyorum ( cut
yeni satırlarda başarısız olanları hariç ):
$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even
new lines
Bazı Perl yolları:
$ perl -pe 's/:/\n/g' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-p
Vasıta "tarafından verilen komut uygulandıktan sonra her giriş hattını yazdırmak -e
". Betik, s/oldnew/
hepsini :
newlines ile değiştirmek için ikame operatörünü ( ) kullanıyor .
$ perl -lne 'print for split /:/' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-l
Her bir yeni satır ekler print
çağrı. Burada, komut dosyası girişini :
bölüyor ve ardından her ayrık öğenin üzerinde dolaşıyor ve yazdırıyor.
$ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-a
Markaları perl
gibi davranmaya awk
: o verdiği karakterin üzerindeki giriş hatlarının her bölecek -F
(böylece :
, burada) ve dizideki sonucu kaydetmek @F
. Bu $"
, değeri yazdırılan bir listenin her elemanı arasında basılan özel bir Perl değişkeni, "liste ayırıcı" dır. Bu yüzden onu yeni bir satıra ayarlamak, print @list
her elemanın @list
ve sonra da yeni bir satırın yazdırılmasını sağlar . Burada, yazdırmak için kullanıyoruz @F
.
$ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Yukarıdaki gibi aynı fikir, sadece daha az golf oynadı. Kullanmak yerine , diziyi $"
açıkça join
yeni satırlarla doldurup yazdırıyoruz.
grep
PCRE sihri ile basit :
$ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-o
Yapar grep
Her bir eşleme ayrı bir satırda basılır, böylece, her bir hattın tek uygun kısmına baskı. -P
Perl Uyumlu Normal İfadeleri (PCRE) sağlar. Düzenli ifade, çizginin başlangıcını ( ) veya bir karakteri izleyen non- :
( [^:]+
) uzantıları arar . Bu , "bu noktadan önce eşleşen her şeyi atmak" anlamına gelen ve aynı zamanda yazdırmayı önlemek için kullanılan bir PCRE numarasıdır . ^
:
\K
:
Ve bir cut
çözüm (bu yeni hatlarda başarısız olur, ancak ters eğik çizgiler ve boşluklarla baş edebilir):
$ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
Kullanılan seçenekler -d:
, giriş sınırlayıcısını ayarlamak :
, -f 1-
yani tüm alanları yazdırmak (1'den sonuna kadar) ve --output-delimiter=$'\n'
iyi, çıkış sınırlandırıcısını ayarlayan anlamına gelir . $'\n'
Olan ANSI C alıntı ve kabuk içinde bir satır karakteri yazdırmak için bir yoldur.
Yukarıdaki örneklerin hepsinde, bir dizeye bir programa girdi olarak iletmek için bash (ve diğer bazı kabukları ') burada string ( <<<
) operatörünü kullanıyorum. Yani command <<<"foo"
eşdeğerdir echo -n "foo" | command
. Unutmayın ki "$PATH"
, tırnak olmadan, kabuk yeni satır karakterini yemiş olur.
@ 7stud , yorumlarda yer almamak için çok iyi olan başka bir yaklaşım daha sundu :
$ perl -0x3a -l012 -pe '' <<<"$PATH"
Golf denen şey budur . -0
Bir sekizli veya onaltılık sayı olarak giriş kayıt ayırıcısını belirtir. Bir "satırı" tanımlayan şey budur ve varsayılan değeri \n
yeni bir satır karakteridir. Burada, bir o kuruyorsun :
olan x3a
altıgen (denemede printf '\x3a\n'
). -l
Üç şey yapar. Önce giriş kaydı ayırıcı (kaldırır $/
her sonundan) hat-etkili bir şekilde çıkarılması :
burada ve ikinci, çıkış kayıt ayırıcı ayarlar ( $\
) ne olursa olsun sekizli ya da altıgen değeri (verilir 012
olan \n
). Eğer $\
tanımlanır, her sonuna eklenir print
bu her eklenen yeni bir satır ile sonuçlanacaktır, böylece çağrı print
.
-pe
İrade s verilen komut uygulandıktan sonra her bir giriş hattını Rint -e
. Burada komut dosyası yok çünkü tüm iş yukarıda açıklanan seçenek bayrakları tarafından yapılıyor!
perl -0x3a -l012 -pe '' <<<$PATH
. Açıklama: -0
giriş kayıt ayırıcısını ayarlar (onaltılık / sekizli notasyonda belirtilir, x3A -l
iki nokta üst üstedir), iki şey yapar: 1) giriş kayıt ayırıcısını sıkar, 2) belirtilmişse çıkış kayıt ayırıcısını ayarlar (sekizlik gösterimde) 012 yeni bir satırdır). Bir -p
döngü, her satırda okunacak olan $ _ değerini yazdırır .
-F
Bilgi için teşekkürler . Ben kullanarak oldum -F
kombine -an
yıllardır, ben diğerleri ima birini fark olmadı. Bu arada, Serg'in Code Golf'ten bahsettiğini gördüm , ama eğer böyle bir şeyle karşılaşırsan Unix & Linux'un da hoşuna gideceğini düşünüyorum .
-l
her baskı çağrısının sonuna verilen çıktı kayıt ayırıcısını da ekler. Aslında, çıktı kayıt ayırıcı tanımlanmışsa, baskı her zaman $/
bir dizenin sonuna çıktı kayıt ayırıcısını ekler . Varsayılan olarak undef'tir. Yani -l
jus ayarlar $/
ve bu da baskı satırının sonuna yeni satır eklemeye neden olur.
Tüm kodlama dilleri zaten alınmış olduğundan, C ile gideceğim. İşleviyle ortam değişkenlerini elde etmek oldukça kolaydır get_env()
(bkz. GNU C Library belgeleri ). Gerisi sadece karakter manipülasyon
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
Fakat aynı zamanda “neden olmasın”, işte komut satırı argümanları aracılığıyla alternatif python sürümü sys.argv
python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"
Ruby, C derleyicisi ve Python yorumlayıcısının aksine, varsayılan olarak Ubuntu ile gelmez, ancak kendinizi kullanırken kendinizi bulursanız, Ruby'deki çözüm şöyle olacaktır:
ruby -ne 'puts $_.split(":")' <<< "$PATH"
7stud önerdiği gibi (Çok teşekkürler!) İçinde yorumlarla , bu da birlikte kısaltılabilir
ruby -F: -ane 'puts $F' <<<$PATH
ve bu taraftan
ruby -0072 -ne 'puts chomp' <<<$PATH
split()
Satırı okumak için diziyi ayırmak için işlevden yararlanabilir ve for-each
her öğeyi ayrı bir satırda yazdırmak için döngü kullanabilirsiniz .
awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
puts
bir dizinin öğelerini otomatik olarak ayrı satırlara yazdırır! Anahtarların da bölünme işlemini yapmasını sağlayabilirsiniz: ruby -F: -ane 'puts $F' <<<$PATH
Açıklama:, String :: split tarafından kullanılan varsayılan ayırıcı olan belirtilen karaktere -F
ayarlar $;
($; -a
$ _. split'i çağırır, burada $ _, gets () kullanarak okunan bir satırdır ve elde edilen diziyi atar $F
.
-F
Bayrak olduğunu bilmiyordum - Ruby ile yeni başlıyorum, bu yüzden işleri biraz kaba bir şekilde yapıyorum.
ruby -0072 -ne 'puts chomp' <<<$PATH
. Açıklama: -0
giriş kayıt ayırıcısını ayarlar (sekizlik biçiminde bir karakter belirtin; 072 iki nokta üst üstedir). Ruby, Perl'e benzer şekillerde $ _ kullanmaktadır. Gets () yöntemi ( -n
döngüde kullanılır ) $ _ değerini okunan geçerli satıra ayarlar . Ve chomp()
bir argüman olmadan, $ _ chomps. Hala senden daha çok hoşlanıyorum. :)
-F
bayraklı olan daha kısadır. Bunu yaparsanız, echo "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c
bunun 271, bayt olduğunu söyler, ancak sekizlik sayıya sahip olan 276'dır. Bu, tüm komut için, elbette, Yalnızca kodun kendisinin puts $F
açıkça daha kısa olduğunu düşünürsek . :) Bu arada, Code Golf'u biliyor musunuz ? Bulmacaları en kısa bayt sayısında programlamaya yönelik çözümler sunar. Bununla ilgili bir soru var: codegolf.stackexchange.com/q/96334/55572
Muhtemelen bahsedilmeyen tek yol, onu yıllardır kullandığım yöntem:
echo $PATH | tr ":" "\n"
bu nedenle, .profile veya .bash_profile veya her neyse, şunu ekleyebilirsiniz:
alias path='echo $PATH | tr ":" "\n"'
Daha fazla Java'ya ihtiyacımız var!
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
Bunu kaydedin GetPathByLine.java
ve aşağıdakileri kullanarak derleyin:
javac GetPathByLine.java
Çalıştır:
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(':')]"
Awk aracılığıyla.
echo $PATH | awk -F: '{for(i=1;i<=NF;i++)print $i}'
Python ile.
$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
for i in line.split(":"):
print(i)'
Girinti python içinde çok önemli olduğunu unutmayın.
echo $PATH | awk '{gsub(/\:/,"\n");print}'
fileinput
Sadece ne zaman kullanabildiğinizle neden input
python3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
Stephen Collyer'in "Bash Path İşlevleri" ni kullanıyorum ( Linux Journal'daki makalesine bakın ). Kabuk programlamada "kolondan ayrılmış listeyi" veri türü olarak kullanmama izin veriyor. Örneğin, şu anki dizindeki tüm dizinlerin bir listesini oluşturabilirim:
dirs="";for i in * ; do if [ -d $i ] ; then addpath -p dirs $i; fi; done
Sonra listpath -p dirs
bir liste oluşturur.
@Cyrus cevabı için açıklama
echo "${PATH//:/$'\n'}"
Notlar:
ANSI-C Quoting - $ 'some \ ntext' ifadesini açıklıyor
Kabuk Parametresi Genişlemesi - $ {parametresini / patern / string} açıklar, patern '/' ile başlarsa, paternin tüm eşleşmeleri dizge ile değiştirilir.
Böylece sahibiz:
Bir başka AWK yolu da, her dizine ayrı bir alan yerine ayrı bir kayıt olarak davranmaktır .
awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
Bu sözdizimini özellikle sezgisel buluyorum. Ancak, isterseniz, print $0
zımni hale getirerek kısaltabilirsiniz (varsayılan eylemdir ve 1
doğru olarak değerlendirilerek her satır için yapılmasına neden olur):
awk 'BEGIN{RS=":"} 1' <<<"$PATH"
AWK'nın varsayılan giriş ve çıkış kayıt ayırıcısı yeni satırdır (satır sonu). Giriş kayıt ayırıcısını ( RS
) :
girişi okumadan önce ayarlayarak, AWK otomatik olarak kolondan $PATH
ayrılmış bir dizin oluşturucunun dizin adlarına ayrıştırır . AWK $0
her bir kayda genişler , yeni satır çıktı kayıt ayırıcı olarak kalır ve döngü veya gsub
gerekli değildir.
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 genellikle kayıtları ayrı alanlara ayrıştırmak için kullanılır, ancak sadece dizin adlarının bir listesini oluşturmak için buna gerek yoktur.
Bu, ardışık boşluk içeren girdiler (boşluklar ve sekmeler) için, hatta ardışık çoklu boşluklar için bile geçerlidir:
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<$'ab\t\t c:de fg:h'
ab c
de fg
h
Diğer bir deyişle, AWK'nın kaydı yeniden oluşturmasına neden olmadıkça (aşağıya bakınız), girişte boşluk veya sekme (varsayılan alan ayırıcıları) olması sorun değildir. Sizin PATH
muhtemelen Ubuntu sisteminde boşluk içermediğinden, ama olursa, bu çalışmaya devam eder.
Bu alanların bir koleksiyon olarak bir kayıt yorumlamak Awk yeteneği olduğunu, bir yan not olarak, bahsetmemiz var olur dizin tablosu inşa ilgili sorun için yararlı bileşenler :
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
Meraklı $1=$1
görev, AWK'yı rekoru yeniden inşa etmeye zorlama amacına hizmet ediyor .
(Bu, bileşenlerin üzerinde ek işlem yapılması gereken durumlar için, sadece tabloyu basmak için gösterilen tam örnek için olduğundan daha faydalıdır.)
jq -Rr 'gsub(":";"\n")' <<<$PATH
Yollar $ PATH'ta ayrı ayrı nasıl gösterilir?
Bunlar, kendi kullanım durumlarıma ve uyumluluk ve kaynak kullanımı hakkındaki endişelerime dayanarak bunu yapmam için tercih ettiğim yöntemler.
tr
Hızlı bir ihtiyacın olursa Öncelikle, hatırlaması kolay bir ve okunabilir çözüm, sadece yankı PATH
ve boru o kadar (tercüme tr
) satırbaşıyla içine iki nokta üst üste açmak için:
echo $PATH | tr : "\n"
Borudan dolayı iki işlemi kullanmanın dezavantajı var, fakat sadece bir terminalde bilgisayar kullanıyorsak, gerçekten umurumuzda mı?
.bashrc
Etkileşimli kullanım için oldukça kalıcı bir çözüm istiyorsanız, aşağıdaki komutu takma ad olarak kullanabilirsiniz path
, ancak bu çözümün okunabilirliği sorgulanabilir:
alias path="echo \"${PATH//:/$'\n'}\""
Desen '/' ile başlıyorsa, tüm desen eşleşmeleri dizeyle değiştirilir. Normalde sadece ilk eşleşme değiştirilir.
Yukarıdaki komut, Bash'in Kabuk Parametresi Genişletme özelliğini kullanarak iki nokta üst üste ile değiştirir :
${parameter/pattern/string}
Açıklamak için:
# v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"
# ^^ ^^^^^----string, $ required to get newline character.
# \----------pattern, / required to substitute for *every* :.
Yine de, komut satırına hacklenirken, eğer takmadıysanız, bunu hatırlamakta iyi şanslar.
Alternatif olarak, kabuktan başka hiçbir şeye dayanmayan, oldukça uyumlu, okunaklı ve anlaşılabilir bir yaklaşım, aşağıdaki işlevi kullanmaktır .bashrc
.
Aşağıdaki işlev geçici olarak Dahili (veya Girdi) Alan Ayırıcısını (IFS) iki nokta üstüste getirir ve bir dizi verildiğinde printf
, dizi kullanılıncaya kadar yürütülür:
path () {
local IFS=:
printf "%s\n" ${PATH}
}
Bu yöntem fonksiyonu oluşturma , IFS
ve printf
bu (ve özellikle Dash olan Ubuntu genellikle takma en POSIX benzeri kabuklarda çalışır, böylece POSIX'in verilmektedir sh
).
Bunun için Python kullanmalı mısınız? Yapabilirdin. Bu, bunun için düşünebileceğim en kısa Python komutudur:
python -c "print('\n'.join('${PATH}'.split(':')))"
veya yalnızca Python 3 (ve belki daha fazla okunabilir?):
python3 -c "print(*'${PATH}'.split(':'), sep='\n')"
Bunlar, Python'unuz olduğu sürece, herhangi bir normal kabuk ortamında da çalışmalıdır.
Bu çözüm Java , C , go ve awk çözümlerinden daha basittir :
$ LPATH=$PATH wine cmd /c echo %LPATH::=$'\n'% 2> /dev/null
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
İşte başka bir büyük olasılık:
$ 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
Bunun için bazı bağımlılıklar kurulmalıdır:
sudo apt-get install openjdk-8-jdk-headless bsh