$PATH
のさまざまなパスを個別にリストする方法がわからないため、次のようになります。
/bin
/usr/bin
/usr/local/bin
等.
誰もこれの正しい変数を知っていますか?
sed
を試してください:
$ sed 's/:/\n/g' <<< "$PATH"
またはtr
:
$ tr ':' '\n' <<< "$PATH"
またはpython
:
$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"
ここでは、上記のすべてが、:
のすべての出現を新しい行\n
に置き換えます。
Bashの Parameter Expansion を使用します。
echo "${PATH//:/$'\n'}"
これにより、:
内のすべての$PATH
が改行(\n
)に置き換えられ、結果が出力されます。 $PATH
の内容は変更されません。
最初の:
のみを置き換える場合は、2番目のスラッシュを削除します:echo -e "${PATH/:/\n}"
IFSの使用:
(set -f; IFS=:; printf "%s\n" $PATH)
IFS
は、bashが分割する文字を保持するため、:
を含むIFS
は、bashが$PATH
上の:
の展開を分割します。 printf
は、引数がなくなるまで書式文字列で引数をループします。 PATHディレクトリ名のワイルドカードが展開されないように、set -f
を使用してグロビング(ワイルドカード展開)を無効にする必要があります。
xargs
を使用:
xargs -n1 -d: <<< $PATH
man xargs
から
-n max-args
Use at most max-args arguments per command line.
-d delim
Input items are terminated by the specified character.
さらにいくつかのアプローチがあります。私はPATH
を使用して、バックスラッシュ、スペース、さらに改行を含むディレクトリを使用します(改行で失敗するcut
を除く)。
$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even
new lines
Perlのいくつかの方法:
$ Perl -pe 's/:/\n/g' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-p
は、「-e
で指定されたスクリプトを適用した後、すべての入力行を印刷する」ことを意味します。スクリプトは、置換演算子(s/oldnew/
)を使用して、すべての:
を改行で置き換えています。
$ Perl -lne 'print for split /:/' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-l
は、各print
呼び出しに改行を追加します。ここで、スクリプトは:
で入力を分割し、各分割要素をループして出力します。
$ Perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-a
はPerl
をawk
のように動作させます。入力行のそれぞれを-F
(ここでは:
)で指定された文字に分割して保存します配列@F
の結果。 $"
は特殊なPerl変数である「リスト区切り文字」であり、その値は印刷リストの各要素の間に印刷されます。したがって、改行に設定すると、print @list
が@list
の各要素を出力し、次に改行を出力します。ここでは、@F
の印刷に使用しています。
$ Perl -F: -ane 'print join "\n", @F' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
上記と同じ考えですが、ゴルフは少なくなります。 $"
を使用する代わりに、明示的に改行で配列をjoin
してから印刷します。
PCREマジックを使用した単純なgrep
:
$ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
-o
はgrep
に各行の一致部分のみを出力させるため、各一致は個別の行に出力されます。 -P
は、Perl Compatible Regular Expressions(PCRE)を有効にします。正規表現は、行の先頭(:
)または[^:]+
文字の後に続く非^
(:
)の範囲を探しています。 \K
は、「この時点より前に一致したものをすべて破棄する」ことを意味するPCREトリックであり、:
も印刷されないようにするためにここで使用されます。
そしてcut
ソリューション(これは改行では失敗しますが、バックスラッシュとスペースを処理できます):
$ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
/bin
usr/bin/
/usr/local/bin
/some\ horrible thing
/even
new lines
使用されるオプションは、入力区切り文字を-d:
に設定する:
、-f 1-
(すべてのフィールド(最初から最後まで)を印刷することを意味します)および--output-delimiter=$'\n'
です。 、出力区切り文字。 $'\n'
は ANSI Cの引用 であり、シェルで改行文字を印刷する方法です。
上記のすべての例で、bash(および他のシェル)を使用しています ここではstring (<<<
)演算子を使用して、文字列をプログラムへの入力として渡します。したがって、command <<<"foo"
はecho -n "foo" | command
と同等です。私は常に"$PATH"
を引用していることに注意してください、引用符なしでは、シェルは改行文字を食べていたでしょう。
$ Perl -0x3a -l012 -pe '' <<<"$PATH"
それが ゴルフ として知られています。 -0
は、入力レコード区切り文字を8進数または16進数として指定します。これが「行」を定義するものであり、そのデフォルト値は\n
、改行文字です。ここでは、:
を16進数でx3a
に設定しています(printf '\x3a\n'
を試してください)。 -l
は3つのことを行います。まず、各行の末尾から入力レコード区切り文字($/
)を削除します(ここで:
を効果的に削除します)。次に、出力レコード区切り文字($\
)を8進数に設定します。または指定された16進値(012
は\n
)。 $\
が定義されている場合、各print
呼び出しの最後に追加されるため、各print
に改行が追加されます。
-pe
は、-e
で指定されたスクリプトを適用した後、各入力行をpリントします。上記のオプションフラグによってすべての作業が行われるため、ここにはスクリプトはありません!
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
すべてのスクリプト言語が既に使用されているため、Cを使用します。get_env()
関数を使用して環境変数を取得するのは非常に簡単です( GNU Cライブラリのドキュメント を参照)。残りは単なる文字操作です
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
しかし、「なぜ」ではないので、コマンドライン引数sys.argv
による代替pythonバージョンもあります
python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"
CコンパイラやPythonインタプリタとは異なり、RubyにはデフォルトではUbuntuが付属していませんが、使用していることに気付いた場合、Rubyのソリューションは次のようになります。
Ruby -ne 'puts $_.split(":")' <<< "$PATH"
comments の7stud(ありがとうございます!)で示唆されているように、これは
Ruby -F: -ane 'puts $F' <<<$PATH
および この方法
Ruby -0072 -ne 'puts chomp' <<<$PATH
split()
関数を使用して、読み取った行を配列に分解し、for-each
ループを使用して、各項目を個別の行に出力できます。
awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
おそらく言及されていない唯一の方法は、私が何年も使用してきた方法です:
echo $PATH | tr ":" "\n"
そのため、.profileまたは.bash_profileなどに次を追加できます。
alias path='echo $PATH | tr ":" "\n"'
さらにJavaが必要です!
public class GetPathByLine {
public static void main(String[] args) {
for (String p : System.getenv("PATH").split(":")) {
System.out.println(p);
}
}
}
これをGetPathByLine.Java
に保存し、次を使用してコンパイルします。
javac GetPathByLine.Java
で実行:
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
Awkを通じて。
echo $PATH | awk -F: '{for(i=1;i<=NF;i++)print $i}'
Python経由。
$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
for i in line.split(":"):
print(i)'
Pythonではインデントが非常に重要であることに注意してください。
@Cyrus回答の説明
echo "${PATH//:/$'\n'}"
ノート:
ANSI-C引用 -$ 'some\ntext'を説明します
シェルパラメーター展開 -$ {parameter/pattern/string}を説明します。パターンが「/」で始まる場合、パターンのすべての一致はストリングに置き換えられます。
だから私たちは持っています:
私はStephen Collyerの「Bash Path Functions」を使用します(Linux Journalの 彼の記事 を参照)。これにより、シェルプログラミングで「コロン区切りリスト」をデータ型として使用できます。たとえば、次の方法で現在のディレクトリ内のすべてのディレクトリのリストを作成できます。
dirs="";for i in * ; do if [ -d $i ] ; then addpath -p dirs $i; fi; done
次に、listpath -p dirs
はリストを作成します。
別のAWKの方法は、各ディレクトリを個別のfieldではなく、個別のrecordとして扱うことです。
awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
この構文は特に直感的です。ただし、必要に応じて、print $0
を暗黙的にすることで短縮できます(デフォルトのアクションであり、1
はtrueと評価され、すべての行で実行されます)。
awk 'BEGIN{RS=":"} 1' <<<"$PATH"
AWKのデフォルトの入力および出力レコード分離記号は改行(改行)です。 AWKは、入力を読み取る前に入力レコードの区切り文字(RS
)を:
に設定することで、コロンで区切られた$PATH
を構成ディレクトリ名に自動的に解析します。 AWKは$0
を各レコード全体に展開し、改行はoutputレコードセパレーターのままであり、ループやgsub
は不要です。
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は、レコードを個別のフィールドに解析するためによく使用されますが、ディレクトリ名のリストを作成するためだけにその必要はありません。
これは、空白(スペースとタブ)、連続する複数の空白を含む入力に対しても機能します。
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<$'ab\t\t c:de fg:h'
ab c
de fg
h
つまり、AWKにレコードをrebuildさせない限り(以下を参照)、入力にスペースやタブ(デフォルトのフィールドセパレーター)が含まれていても問題はありません。おそらくPATH
にはUbuntuシステム上にスペースが含まれていない可能性がありますが、スペースが含まれていても機能します。
サイドノートとして、レコードをフィールドのコレクションとして解釈するAWKの機能になるディレクトリのテーブルを構築する関連問題コンポーネント:
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
好奇心盛な$1=$1
割り当ては、AWKを強制する目的を果たします レコードを再構築するため 。
(これは、表を単に印刷するという正確な例よりも、コンポーネントで追加の処理を行う場合におそらく役立つでしょう。)
jq -Rr 'gsub(":";"\n")' <<<$PATH
このソリューションは、Java、C、goおよびawkソリューションよりも簡単です。
$ LPATH=$PATH wine cmd /c echo %LPATH::=$'\n'% 2> /dev/null
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
別の素晴らしい可能性があります:
$ 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
これには、いくつかの依存関係をインストールする必要があります。
Sudo apt-get install openjdk-8-jdk-headless bsh
$ PATHのパスを個別に表示する方法
これらは、それぞれのユースケースと互換性とリソース使用量に関する懸念に基づいて、これを行うための好ましい方法です。
tr
最初に、覚えやすくて読みやすい迅速な解決策が必要な場合は、PATH
をエコーし、 translate(tr
) にパイプして、コロンを改行に変換します。
echo $PATH | tr : "\n"
パイプが原因で2つのプロセスを使用するというデメリットがありますが、単に端末をハッキングしているだけなら、本当に気になりますか?
.bashrc
に永続的なソリューションをインタラクティブに使用したい場合は、次のコマンドをpath
にエイリアスできますが、このソリューションの可読性は疑問です。
alias path="echo \"${PATH//:/$'\n'}\""
パターンが「/」で始まる場合、パターンの一致はすべて文字列に置き換えられます。通常、最初の一致のみが置き換えられます。
上記のコマンドは、Bashの Shell Parameter Expansion を使用してコロンを改行に置き換えます。
${parameter/pattern/string}
説明するには:
# v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"
# ^^ ^^^^^----string, $ required to get newline character.
# \----------pattern, / required to substitute for *every* :.
ただし、エイリアスを作成していない場合は、コマンドラインでハッキングしているときにこれを思い出してください。
あるいは、シェル以外に依存しない、かなり相互互換性があり、読み取り可能で、理解可能なアプローチは、次の関数を使用することです(.bashrc
で提案します)。
次の関数は、内部(または入力)フィールドセパレーター(IFS)を一時的にコロンにし、配列がprintf
に与えられると、配列が使い果たされるまで実行されます。
path () {
local IFS=:
printf "%s\n" ${PATH}
}
関数の作成 、 IFS
、および printf
のこのメソッドはposixで提供されているため、ほとんどのposixのようなシェル(特にDash)で動作するはずです。 、これはUbuntuが通常sh
としてエイリアスします)。
これにはPythonを使用する必要がありますか?あなたは出来る。これは、これについて考えることができる最短のPythonコマンドです。
python -c "print('\n'.join('${PATH}'.split(':')))"
またはPython 3のみ(そしておそらくもっと読みやすい?):
python3 -c "print(*'${PATH}'.split(':'), sep='\n')"
Pythonを持っている限り、これらは通常のシェル環境でも動作するはずです。