1. ホーム
  2. bash

[解決済み] Bashで$PATH変数からパスを削除する最もエレガントな方法は何ですか?

2022-08-12 19:08:30

質問

より一般的には、Bash 環境変数のコロンで区切られたリストから項目を削除するにはどうしたらよいでしょうか。

何年も前に、Bash の変数展開のより高度なフォームを使用して、これを行う簡単な方法を見たことがあると思ったのですが、もしそうなら、私はそれを見失っていました。 Google ですばやく検索すると、驚くほど少数の関連する結果が見つかり、私が単純またはエレガントと呼ぶものはありません。 例えば、sed と awk をそれぞれ使用する 2 つの方法です。

PATH=$(echo $PATH | sed -e 's;:\?/home/user/bin;;' -e 's;/home/user/bin:\?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)

ストレートなものは存在しないのでしょうか? Bashのsplit()関数に相当するものはないのでしょうか?

更新しました。

私は特定のユースケースを解決することよりも、良い議論を引き起こすことに興味があったのですが、意図的に曖昧な質問をしたことを謝らなければならないようです。 幸いなことに、私はそれを得ました!

ここには、非常に巧妙なテクニックがあります。 最終的に、私は以下の 3 つの関数を私のツールボックスに追加しました。 魔法は path_remove で起こりますが、これは Martin York の巧妙な awk の RS 変数の巧みな使用に基づいています。

path_append ()  { path_remove $1; export PATH="$PATH:$1"; }
path_prepend () { path_remove $1; export PATH="$1:$PATH"; }
path_remove ()  { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; }

この中で唯一本当にくだらないのは sed を使用して、末尾のコロンを削除していることです。 しかし、Martin のソリューションの残りの部分がいかに簡単であるかを考えると、私はそれに耐えることができます!


関連する質問です。 シェルスクリプトで $PATH 要素を操作するにはどうしたらいいですか?

どのように解決するのですか?

awkで1分。

# Strip all paths with SDE in them.
#
export PATH=`echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}'`

編集:以下のコメントへの対応です。

$ export a="/a/b/c/d/e:/a/b/c/d/g/k/i:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i"
$ echo ${a}
/a/b/c/d/e:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i

## Remove multiple (any directory with a: all of them)
$ echo ${a} | awk -v RS=: -v ORS=: '/a/ {next} {print}'
## Works fine all removed

## Remove multiple including last two: (any directory with g)
$ echo ${a} | awk -v RS=: -v ORS=: '/g/ {next} {print}'
/a/b/c/d/e:/a/b/c/d/f:
## Works fine: Again!

セキュリティ問題への対応で編集:(質問とは関係ないことですが)

export PATH=$(echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}' | sed 's/:*$//')

これは、最後のエントリを削除することによって残った末尾のコロンを削除し、効果的に . をパスに追加することになります。