Какой самый элегантный способ удалить путь из переменной $ PATH в Bash? - PullRequest
99 голосов
/ 16 декабря 2008

Или, в более общем смысле, как удалить элемент из списка, разделенного двоеточиями, в переменной среды Bash?

Мне показалось, что я видел простой способ сделать это несколько лет назад, используя более продвинутые формы расширения переменных Bash, но если это так, я потерял след. Быстрый поиск в Google показал удивительно мало релевантных результатов и ни одного, который я бы назвал «простым» или «элегантным». Например, два метода с использованием sed и awk соответственно:

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)

Ничего простого не существует? Есть ли что-нибудь аналогичное функции split () в Bash?

Обновление:
Похоже, мне нужно извиниться за мой намеренно неопределенный вопрос; Меня меньше интересовало решение конкретного варианта использования, чем провоцирование хорошей дискуссии. К счастью, я понял!

Здесь есть несколько очень умных техник. В конце я добавил следующие три функции в свою панель инструментов. Волшебство происходит в path_remove, в основе которого лежит умное использование Мартином Йорком переменной 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 для удаления заднего двоеточия. Учитывая то, насколько простым является решение Мартина, я вполне готов с этим смириться!


Смежный вопрос: Как мне манипулировать элементами $ PATH в скриптах оболочки?

Ответы [ 34 ]

0 голосов
/ 16 декабря 2008

Что делает эту проблему раздражающей, так это случаи ограждения среди первых и последних элементов. Эту проблему можно элегантно решить, изменив IFS и используя массив, но я не знаю, как заново ввести двоеточие после преобразования пути в форму массива.

Вот немного менее элегантная версия, которая удаляет один каталог из $PATH, используя только манипуляции со строками. Я проверил это.

#!/bin/bash
#
#   remove_from_path dirname
#
#   removes $1 from user's $PATH

if [ $# -ne 1 ]; then
  echo "Usage: $0 pathname" 1>&2; exit 1;
fi

delendum="$1"
NEWPATH=
xxx="$IFS"
IFS=":"
for i in $PATH ; do
  IFS="$xxx"
  case "$i" in
    "$delendum") ;; # do nothing
    *) [ -z "$NEWPATH" ] && NEWPATH="$i" || NEWPATH="$NEWPATH:$i" ;;
  esac
done

PATH="$NEWPATH"
echo "$PATH"
0 голосов
/ 21 января 2010

Расширенная односторонняя окантовка (ну, вроде):

path_remove ()  { shopt -s extglob; PATH="${PATH//+(${1})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; } 

Кажется, нет необходимости избегать слешей в $ 1.

path_remove ()  { shopt -s extglob; declare escArg="${1//\//\\/}"; PATH="${PATH//+(${escArg})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; } 
0 голосов
/ 28 апреля 2019

Давайте «удалим» ссылки на / path / to / что-то из PATH:

Bash:

PATH=${PATH/something/nope/}

Бонусный ответ для Windows Batch:

set PATH=%PATH:something=nope%

У кого-нибудь есть более простое решение? :)

0 голосов
/ 23 июня 2011

Хотя это очень старая тема, я подумал, что это решение может быть интересным:

PATH="/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
REMOVE="ccache" # whole or part of a path :)
export PATH=$(IFS=':';p=($PATH);unset IFS;p=(${p[@]%%$REMOVE});IFS=':';echo "${p[*]}";unset IFS)
echo $PATH # outputs /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

нашел его в этом блоге . Я думаю, что мне больше всего нравится этот:)

...