PATH 環境変数からディレクトリの重複コピーを削除できる bash シェル関数を作成しようとしています。
コマンドを使用して 1 行のコマンドでこれを実現できると聞きましたawk
が、その方法がわかりません。誰か方法を知っていますか?
答え1
すでに重複したディレクトリがなくPATH
、まだ存在しないディレクトリのみを追加したい場合は、シェルだけで簡単に実行できます。
for x in /path/to/add …; do
case ":$PATH:" in
*":$x:"*) :;; # already there
*) PATH="$x:$PATH";;
esac
done
以下は、 から重複を削除するシェル スニペットです$PATH
。エントリを 1 つずつ調べて、まだ表示されていないエントリをコピーします。
if [ -n "$PATH" ]; then
old_PATH=$PATH:; PATH=
while [ -n "$old_PATH" ]; do
x=${old_PATH%%:*} # the first remaining entry
case $PATH: in
*:"$x":*) ;; # already there
*) PATH=$PATH:$x;; # not there yet
esac
old_PATH=${old_PATH#*:}
done
PATH=${PATH#:}
unset old_PATH x
fi
答え2
これは理解できるすべてを適切に実行するワンライナー ソリューション: 重複を削除し、パスの順序を維持し、最後にコロンを追加しません。したがって、元の PATH とまったく同じ動作をする重複排除された PATH が提供されるはずです。
PATH="$(perl -e 'print join(":", grep { not $seen{$_}++ } split(/:/, $ENV{PATH}))')"
これは単にコロン ( split(/:/, $ENV{PATH})
) で分割し、を使用してgrep { not $seen{$_}++ }
最初の出現を除くパスの繰り返しインスタンスをフィルター処理し、残りのものをコロンで区切って結合し、結果を出力します ( print join(":", ...)
)。
さらに構造を追加し、他の変数の重複を排除する機能も必要な場合は、現在自分の設定で使用している次のスニペットを試してください。
# Deduplicate path variables
get_var () {
eval 'printf "%s\n" "${'"$1"'}"'
}
set_var () {
eval "$1=\"\$2\""
}
dedup_pathvar () {
pathvar_name="$1"
pathvar_value="$(get_var "$pathvar_name")"
deduped_path="$(perl -e 'print join(":",grep { not $seen{$_}++ } split(/:/, $ARGV[0]))' "$pathvar_value")"
set_var "$pathvar_name" "$deduped_path"
}
dedup_pathvar PATH
dedup_pathvar MANPATH
このコードは PATH と MANPATH の両方の重複を排除し、dedup_pathvar
コロンで区切られたパスのリスト (例: PYTHONPATH) を保持する他の変数を簡単に呼び出すことができます。
答え3
ここに洗練されたものがあります:
printf %s "$PATH" | awk -v RS=: -v ORS=: '!arr[$0]++'
もっと長く(どのように動作するかを見るため):
printf %s "$PATH" | awk -v RS=: -v ORS=: '{ if (!arr[$0]++) { print $0 } }'
さて、Linux を初めて使用するので、末尾に「:」を付けずに PATH を実際に設定する方法を説明します。
PATH=`printf %s "$PATH" | awk -v RS=: '{ if (!arr[$0]++) {printf("%s%s",!ln++?"":":",$0)}}'`
ちなみに、PATH に「:」を含むディレクトリがないようにしてください。そうでないと、おかしくなります。
謝辞:
答え4
awk 以外のワンライナーを追加する限り:
PATH=$(zsh -fc "typeset -TU P=$PATH p; echo \$P")
( のように単純になることもありますPATH=$(zsh -fc 'typeset -U path; echo $PATH')
が、zsh は常に少なくとも 1 つのzshenv
設定ファイルを読み取り、 を変更する可能性がありますPATH
。)
2 つの優れた zsh 機能を使用します。
- 配列に結び付けられたスカラー (
typeset -T
) - 重複する値を自動的に削除する配列 (
typeset -U
)。