web-dev-qa-db-ja.com

$ PATHのパスを個別に表示する方法

$PATHのさまざまなパスを個別にリストする方法がわからないため、次のようになります。

/bin
/usr/bin
/usr/local/bin

等.

誰もこれの正しい変数を知っていますか?

42
HankG

sedを試してください:

$ sed 's/:/\n/g' <<< "$PATH"

またはtr

$ tr ':' '\n' <<< "$PATH"

またはpython

$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"

ここでは、上記のすべてが、:のすべての出現を新しい行\nに置き換えます。

55
heemayl

Bashの Parameter Expansion を使用します。

echo "${PATH//:/$'\n'}"

これにより、:内のすべての$PATHが改行(\n)に置き換えられ、結果が出力されます。 $PATHの内容は変更されません。
最初の:のみを置き換える場合は、2番目のスラッシュを削除します:echo -e "${PATH/:/\n}"

61
Cyrus

IFSの使用:

(set -f; IFS=:; printf "%s\n" $PATH)

IFSは、bashが分割する文字を保持するため、:を含むIFSは、bashが$PATH上の:の展開を分割します。 printfは、引数がなくなるまで書式文字列で引数をループします。 PATHディレクトリ名のワイルドカードが展開されないように、set -fを使用してグロビング(ワイルドカード展開)を無効にする必要があります。

26
muru

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.
14
souravc

さらにいくつかのアプローチがあります。私は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
    

    -aPerlawkのように動作させます。入力行のそれぞれを-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
    

    -ogrepに各行の一致部分のみを出力させるため、各一致は個別の行に出力されます。 -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"を引用していることに注意してください、引用符なしでは、シェルは改行文字を食べていたでしょう。


@ 7studコメント で別のアプローチを提供しました。

$ 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リントします。上記のオプションフラグによってすべての作業が行われるため、ここにはスクリプトはありません!

7
terdon

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
7
Nathan Osman

この答えでは:

  1. C
  2. Python
  3. Ruby
  4. 代替awk

1. C

すべてのスクリプト言語が既に使用されているため、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

2. Python

しかし、「なぜ」ではないので、コマンドライン引数sys.argvによる代替pythonバージョンもあります

python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"

3.ルビー

CコンパイラやPythonインタプリタとは異なり、RubyにはデフォルトではUbuntuが付属していませんが、使用していることに気付いた場合、Rubyのソリューションは次のようになります。

Ruby -ne 'puts $_.split(":")' <<< "$PATH"

comments の7stud(ありがとうございます!)で示唆されているように、これは

Ruby -F: -ane 'puts $F' <<<$PATH

および この方法

Ruby -0072 -ne 'puts chomp' <<<$PATH

4.代替awk

split()関数を使用して、読み取った行を配列に分解し、for-eachループを使用して、各項目を個別の行に出力できます。

awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH
6

おそらく言及されていない唯一の方法は、私が何年も使用してきた方法です:

echo $PATH | tr ":" "\n"

そのため、.profileまたは.bash_profileなどに次を追加できます。

alias path='echo $PATH | tr ":" "\n"'

5
dolt

さらに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
4
Kaz Wolfe

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ではインデントが非常に重要であることに注意してください。

3
Avinash Raj

@Cyrus回答の説明

echo "${PATH//:/$'\n'}"

ノート:

ANSI-C引用 -$ 'some\ntext'を説明します

シェルパラメーター展開 -$ {parameter/pattern/string}を説明します。パターンが「/」で始まる場合、パターンのすべての一致はストリングに置き換えられます。

だから私たちは持っています:

  1. 「/」で始まるすべての一致を置換するパターン/:
  2. 文字列$ '\ n'。これは、改行記号(\ n)を処理するために$ 'anytext'縮約で引用されます。
2
victorq10

私は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はリストを作成します。

2
waltinator

別の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を強制する目的を果たします レコードを再構築するため

(これは、表を単に印刷するという正確な例よりも、コンポーネントで追加の処理を行う場合におそらく役立つでしょう。)

1
Eliah Kagan
jq -Rr 'gsub(":";"\n")' <<<$PATH
1
David Fetter

このソリューションは、JavaCgoおよび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
0
Gungwald

$ PATHのパスを個別に表示する方法

これらは、それぞれのユースケースと互換性とリソース使用量に関する懸念に基づいて、これを行うための好ましい方法です。

tr

最初に、覚えやすくて読みやすい迅速な解決策が必要な場合は、PATHをエコーし​​、 translate(tr にパイプして、コロンを改行に変換します。

echo $PATH | tr : "\n"

パイプが原因で2つのプロセスを使用するというデメリットがありますが、単に端末をハッキングしているだけなら、本当に気になりますか?

Bashのシェルパラメーター展開

.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* :.

ただし、エイリアスを作成していない場合は、コマンドラインでハッキングしているときにこれを思い出してください。

IFS、BashおよびDashでテスト済み

あるいは、シェル以外に依存しない、かなり相互互換性があり、読み取り可能で、理解可能なアプローチは、次の関数を使用することです(.bashrcで提案します)。

次の関数は、内部(または入力)フィールドセパレーター(IFS)を一時的にコロンにし、配列がprintfに与えられると、配列が使い果たされるまで実行されます。

path () {
    local IFS=:
    printf "%s\n" ${PATH}
    }

関数の作成IFS 、および printf のこのメソッドはposixで提供されているため、ほとんどのposixのようなシェル(特にDash)で動作するはずです。 、これはUbuntuが通常shとしてエイリアスします)。

Python

これにはPythonを使用する必要がありますか?あなたは出来る。これは、これについて考えることができる最短のPythonコマンドです。

python -c "print('\n'.join('${PATH}'.split(':')))"

またはPython 3のみ(そしておそらくもっと読みやすい?):

python3 -c "print(*'${PATH}'.split(':'), sep='\n')"

Pythonを持っている限り、これらは通常のシェル環境でも動作するはずです。

0
Aaron Hall