PATHに改行文字を含めることはできますか?

PATHに改行文字を含めることはできますか?

私たちが知っているように、パスにはすべてのコンポーネントに改行文字を含めることができます。

$PATHそれでは、環境変数に改行文字を含めることができると結論付けるべきですか?

$PATHそれでは、Bourne likeのように要素にどのように分割できますか?

    IFS=':' ; set -f
    for var in $PATH
    do
        echo "<$var>"
    done

ただし、IFSを変更せずに実行できる場合は、より良いでしょう。

答え1

POSIX シェルには$IFSフィールドがあります。区切り記号、区切り文字の代わりにこれら$PATHの値は、空の文字列(現在のディレクトリを表す)の代わりに分割され/bin:/usr/bin:ます。以下を行う必要があります。/bin/usr/bin/bin/usr/bin

IFS=:; set -o noglob
for var in $PATH""; do
  printf '<%s>\n' "$var"
done

グローバル設定の変更を防ぐために、明示的な分割演算子でシェルを使用できますzsh。たとえば、次のようになります。

for var in "${(s/:/@)PATH}"; do
  printf '<%s>\n' "$var"
done

この場合、配列はzshすでに$path/にバインドされているため、$PATH次のようになります。cshtcsh

for var in "$path[@]"; do
  printf '<%s>\n' "$var"
done

とにかく、そうです。理論的には、$PATHすべての変数に改行文字を含めることができるように、改行文字はファイルパスの解析では特別ではありません。私は、識別可能な人が名前$PATHに改行(またはワイルドカード)を含むディレクトリを置くか、改行を含むコマンド名を指定することを期待していません。$PATH改行が含まれていないと仮定するスクリプトを誰かが利用できるシナリオも想像するのは難しいです。

答え2

はい、PATH改行文字を含めることができます(古いUnixシステムでも同様です)。

シェルで文字列を分割する場合、唯一の移植可能な方法はを使用することです。ただし、ループを使用する代わりに、それを使用したり関数に渡したりIFSできます。IFS=:; set -f; set -- $PATHfor

bash文字列を「読む」こともできます。大量に:

xtra=$'some\nother\nplace\n\n'; PATH="$PATH:$xtra"
mapfile -td: path < <(printf %s "$PATH")
printf '<%s>\n' "${path[@]}"

しかし、配列を使用することは、環境変数に透過的に格納したり、外部コマンドに単一の引数として渡したりすることはできないため、通常は良い考えではありません。

IFSなります。終了\nフィールドを区別する代わりに(ファイルを1行ずつ読み取るプログラムでファイルの終わりを空行として扱わないのと似ています)、これが期待される結果ではなく実際に分割できるようにしたい場合は、文字で終わる文字列の末尾に追加の空のフィールドを作成します。するにはIFS、単語を分割したい変数の後に空の文字列を追加する必要があります。

(P=/bin:; IFS=:; printf '<%s>\n' $P"")
</bin>
<>

IFS単語分割アルゴリズムは、空白文字が文字列の一部である場合、文字列の先頭の空白文字も無視します。追加フィールドを先行スペースとして使用するには、変数の前に空の文字列も含める必要があります。

(P='   foo : bar  '; IFS=': '; set -f; set -- $P; printf '<%s>\n' "$@")
<foo>
<bar>

(P='   foo : bar  '; IFS=': '; set -f; set -- ""$P""; printf '<%s>\n' "$@")
<>
<foo>
<bar>
<>

関連情報