Какой самый элегантный способ удалить путь из переменной $PATH в Bash?
-
21-08-2019 - |
Вопрос
Или, в более общем плане, как удалить элемент из списка, разделенного двоеточиями, в переменной среды 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 в сценариях оболочки?
Решение
Минута с awk:
# 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/:*$//')
Это удалит все оставшиеся двоеточия, удалив последние записи, что фактически добавит .
на твой путь.
Другие советы
Мой грязный хак:
echo ${PATH} > t1
vi t1
export PATH=$(cat t1)
Поскольку большая проблема с заменой — это конечные случаи, как насчет того, чтобы конечные случаи ничем не отличались от других случаев?Если бы в начале и конце пути уже были двоеточия, мы могли бы просто найти нужную строку, заключенную в двоеточия.На самом деле мы можем легко добавить эти двоеточия и впоследствии удалить их.
# PATH => /bin:/opt/a dir/bin:/sbin
WORK=:$PATH:
# WORK => :/bin:/opt/a dir/bin:/sbin:
REMOVE='/opt/a dir/bin'
WORK=${WORK/:$REMOVE:/:}
# WORK => :/bin:/sbin:
WORK=${WORK%:}
WORK=${WORK#:}
PATH=$WORK
# PATH => /bin:/sbin
Чистый баш :).
Вот самое простое решение, которое я могу придумать:
#!/bin/bash
IFS=:
# convert it to an array
t=($PATH)
unset IFS
# perform any array operations to remove elements from the array
t=(${t[@]%%*usr*})
IFS=:
# output the new array
echo "${t[*]}"
В приведенном выше примере будет удален любой элемент в $PATH, содержащий «usr».Вы можете заменить «*usr*» на «/home/user/bin», чтобы удалить только этот элемент.
обновлять за Сшуберт
Хотя я думаю, что пробелы в $PATH
область ужасный идея, вот решение, которое справится с этим:
PATH=$(IFS=':';t=($PATH);n=${#t[*]};a=();for ((i=0;i<n;i++)); do p="${t[i]%%*usr*}"; [ "${p}" ] && a[i]="${p}"; done;echo "${a[*]}");
или
IFS=':'
t=($PATH)
n=${#t[*]}
a=()
for ((i=0;i<n;i++)); do
p="${t[i]%%*usr*}"
[ "${p}" ] && a[i]="${p}"
done
echo "${a[*]}"
Вот однострочник, который, несмотря на нынешнюю принял и наивысший рейтинг ответы, не добавляет в PATH невидимые символы и справляется с путями, содержащими пробелы:
export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/cygwin/" | tr "\n" ":"); echo ${p%:})
Лично я также нахожу это простым для чтения/понимания, и оно включает только общие команды вместо использования awk.
Вот решение, которое:
- это чистый Баш,
- не вызывает другие процессы (например, «sed» или «awk»),
- не меняется
IFS
, - не разветвляет подоболочку,
- обрабатывает пути с пробелами и
удаляет все вхождения аргумента в
PATH
.removeFromPath() { local p d p=":$1:" d=":$PATH:" d=${d//$p/:} d=${d/#:/} PATH=${d/%:/} }
функция __path_remove(){
локальный D=":${PATH}:";
[ "${D/:$1:/:}" != "$D" ] && PATH="${D/:$1:/:}";
PATH="${PATH/#:/}";
экспортировать PATH="${PATH/%:/}";
}
Выкопал это из моего файла .bashrc.Когда вы играете с PATH и он теряется, awk/sed/grep становится недоступным :-)
Лучший вариант чистого bash, который я нашел на данный момент, следующий:
function path_remove {
PATH=${PATH/":$1"/} # delete any instances in the middle or at the end
PATH=${PATH/"$1:"/} # delete any instances at the beginning
}
Это основано на не совсем правильный ответ к Добавьте каталог в $PATH, если его там еще нет. на Суперпользователе.
Я просто использовал функции из дистрибутива bash, которые, по-видимому, существуют с 1991 года.Они все еще находятся в пакете bash-docs в Fedora и раньше использовались в /etc/profile
, но не более...
$ rpm -ql bash-doc |grep pathfunc
/usr/share/doc/bash-4.2.20/examples/functions/pathfuncs
$ cat $(!!)
cat $(rpm -ql bash-doc |grep pathfunc)
#From: "Simon J. Gerraty" <sjg@zen.void.oz.au>
#Message-Id: <199510091130.VAA01188@zen.void.oz.au>
#Subject: Re: a shell idea?
#Date: Mon, 09 Oct 1995 21:30:20 +1000
# NAME:
# add_path.sh - add dir to path
#
# DESCRIPTION:
# These functions originated in /etc/profile and ksh.kshrc, but
# are more useful in a separate file.
#
# SEE ALSO:
# /etc/profile
#
# AUTHOR:
# Simon J. Gerraty <sjg@zen.void.oz.au>
# @(#)Copyright (c) 1991 Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
# Permission to copy, redistribute or otherwise
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
# is $1 missing from $2 (or PATH) ?
no_path() {
eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
}
я написал на это ответ здесь (тоже используя awk).Но я не уверен, что это то, что вы ищете?По крайней мере, мне кажется ясным, что он делает, вместо того, чтобы пытаться уместиться в одну линию.Однако для простого одного лайнера, который удаляет только вещи, я рекомендую
echo $PATH | tr ':' '\n' | awk '$0 != "/bin"' | paste -sd:
Замена
echo $PATH | tr ':' '\n' |
awk '$0 != "/bin"; $0 == "/bin" { print "/bar" }' | paste -sd:
или (короче, но менее читабельно)
echo $PATH | tr ':' '\n' | awk '$0 == "/bin" { print "/bar"; next } 1' | paste -sd:
В любом случае, тот же вопрос и множество полезных ответов см. здесь.
Ну, в bash, поскольку он поддерживает регулярные выражения, я бы просто сделал:
PATH=${PATH/:\/home\/user\/bin/}
Какой самый элегантный способ удалить путь из переменной $PATH в Bash?
Что может быть элегантнее, чем awk?
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`;
Питон!Это более читаемое и удобное в сопровождении решение, и его легко проверить, чтобы убедиться, что оно действительно делает то, что вы хотите.
Скажем, вы хотите удалить первый элемент пути?
PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
(Вместо трубопровода из echo
, os.getenv['PATH']
будет немного короче и даст тот же результат, что и выше, но я беспокоюсь, что Python может что-то сделать с этой переменной среды, поэтому, вероятно, лучше передать ее непосредственно из интересующей вас среды.)
Аналогично удалить с конца:
PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
Чтобы создать эти повторно используемые функции оболочки, которые вы можете, например, вставить в свой файл .bashrc:
strip_path_first () {
PATH="$(echo "$PATH" |
python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
}
strip_path_last () {
PATH="$(echo "$PATH" |
python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
}
Да, например, установка двоеточия в конце PATH делает удаление пути менее громоздким и подверженным ошибкам.
path_remove () {
declare i newPATH
newPATH="${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
#echo ${@:${i}:1}
newPATH="${newPATH//${@:${i}:1}:/}"
done
export PATH="${newPATH%:}"
return 0;
}
path_remove_all () {
declare i newPATH
shopt -s extglob
newPATH="${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
newPATH="${newPATH//+(${@:${i}:1})*([^:]):/}"
#newPATH="${newPATH//+(${@:${i}:1})*([^:])+(:)/}"
done
shopt -u extglob
export PATH="${newPATH%:}"
return 0
}
path_remove /opt/local/bin /usr/local/bin
path_remove_all /opt/local /usr/local
Если вы беспокоитесь об удалении дубликаты в $PATH, ИМХО, самым элегантным способом было бы не добавлять их вообще.В 1 строке:
if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$folder" ) ; then PATH=$PATH:$folder ; fi
$folder может быть заменен чем угодно и может содержать пробелы («/home/user/my document»)
Самое элегантное чистое решение bash, которое я нашел на сегодняшний день:
pathrm () {
local IFS=':'
local newpath
local dir
local pathvar=${2:-PATH}
for dir in ${!pathvar} ; do
if [ "$dir" != "$1" ] ; then
newpath=${newpath:+$newpath:}$dir
fi
done
export $pathvar="$newpath"
}
pathprepend () {
pathrm $1 $2
local pathvar=${2:-PATH}
export $pathvar="$1${!pathvar:+:${!pathvar}}"
}
pathappend () {
pathrm $1 $2
local pathvar=${2:-PATH}
export $pathvar="${!pathvar:+${!pathvar}:}$1"
}
Большинство других предлагаемых решений полагаются только на сопоставление строк и не учитывают сегменты пути, содержащие специальные имена, такие как .
, ..
, или ~
.Приведенная ниже функция bash разрешает строки каталогов в своем аргументе и в сегментах пути, чтобы найти логические совпадения каталогов, а также совпадения строк.
rm_from_path() {
pattern="${1}"
dir=''
[ -d "${pattern}" ] && dir="$(cd ${pattern} && pwd)" # resolve to absolute path
new_path=''
IFS0=${IFS}
IFS=':'
for segment in ${PATH}; do
if [[ ${segment} == ${pattern} ]]; then # string match
continue
elif [[ -n ${dir} && -d ${segment} ]]; then
segment="$(cd ${segment} && pwd)" # resolve to absolute path
if [[ ${segment} == ${dir} ]]; then # logical directory match
continue
fi
fi
new_path="${new_path}${IFS}${segment}"
done
new_path="${new_path/#${IFS}/}" # remove leading colon, if any
IFS=${IFS0}
export PATH=${new_path}
}
Тест:
$ mkdir -p ~/foo/bar/baz ~/foo/bar/bif ~/foo/boo/bang
$ PATH0=${PATH}
$ PATH=~/foo/bar/baz/.././../boo/././../bar:${PATH} # add dir with special names
$ rm_from_path ~/foo/boo/../bar/. # remove same dir with different special names
$ [ ${PATH} == ${PATH0} ] && echo 'PASS' || echo 'FAIL'
Linux from Scratch определяет три функции Bash в /etc/profile
:
# Functions to help us manage paths. Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
local IFS=':'
local NEWPATH
local DIR
local PATHVARIABLE=${2:-PATH}
for DIR in ${!PATHVARIABLE} ; do
if [ "$DIR" != "$1" ] ; then
NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
fi
done
export $PATHVARIABLE="$NEWPATH"
}
pathprepend () {
pathremove $1 $2
local PATHVARIABLE=${2:-PATH}
export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}
pathappend () {
pathremove $1 $2
local PATHVARIABLE=${2:-PATH}
export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}
export -f pathremove pathprepend pathappend
Ссылка: http://www.linuxfromscratch.org/blfs/view/svn/postlfs/profile.html
Мне нравятся три функции, показанные в обновлении @BenBlank к его первоначальному вопросу.Чтобы обобщить их, я использую форму с двумя аргументами, которая позволяет мне установить PATH или любую другую переменную среды, которую я хочу:
path_append () { path_remove $1 $2; export $1="${!1}:$2"; }
path_prepend () { path_remove $1 $2; export $1="$2:${!1}"; }
path_remove () { export $1="`echo -n ${!1} | awk -v RS=: -v ORS=: '$1 != "'$2'"' | sed 's/:$//'`"; }
Примеры использования:
path_prepend PATH /usr/local/bin
path_append PERL5LIB "$DEVELOPMENT_HOME/p5/src/perlmods"
Обратите внимание, что я также добавил несколько кавычек, чтобы обеспечить правильную обработку имен путей, содержащих пробелы.
Поскольку это, как правило, довольно проблематично, поскольку элегантного способа НЕТ, я рекомендую избежать проблемы, переставив решение:создайте свой ПУТЬ, а не пытайтесь его разрушить.
Я мог бы быть более конкретным, если бы знал ваш реальный контекст проблемы.Тем временем я буду использовать сборку программного обеспечения в качестве контекста.
Распространенная проблема со сборками программного обеспечения заключается в том, что оно не работает на некоторых машинах, в конечном итоге из-за того, как кто-то настроил оболочку по умолчанию (PATH и другие переменные среды).Элегантное решение — сделать ваши сценарии сборки невосприимчивыми, полностью указав среду оболочки.Напишите свои сценарии сборки, чтобы установить PATH и другие переменные среды на основе частей сборки, которыми вы управляете, таких как расположение компилятора, библиотек, инструментов, компонентов и т. д.Сделайте каждый настраиваемый элемент чем-то, что вы можете индивидуально установить, проверить и затем соответствующим образом использовать в своем сценарии.
Например, у меня есть сборка Java, ориентированная на WebLogic, на основе Maven, которую я унаследовал от своего нового работодателя.Сценарий сборки известен своей хрупкостью, и мы с еще одним новым сотрудником потратили три недели (не полный рабочий день, просто здесь и там, но все же много часов), чтобы заставить его работать на наших машинах.Важным шагом было то, что я взял под свой контроль PATH, чтобы точно знать, какой Java, какой Maven и какой WebLogic вызывается.Я создал переменные среды, указывающие на каждый из этих инструментов, а затем рассчитал PATH на основе этих плюс нескольких других.Подобные методы приручали другие настраиваемые параметры, пока мы, наконец, не создали воспроизводимую сборку.
Кстати, не используйте Maven, с Java все в порядке, и покупайте WebLogic только в том случае, если вам абсолютно необходима его кластеризация (но в остальном нет, и особенно не его фирменные функции).
С наилучшими пожеланиями.
Как и в случае с @litb, я ответил на вопрос "Как манипулировать элементами $PATH в сценариях оболочки", так что мой главный ответ там.
Функция «разделения» в bash
и других производных оболочки Борна наиболее аккуратно достигается с помощью $IFS
, разделитель между полями.Например, чтобы установить позиционные аргументы ($1
, $2
, ...) к элементам PATH используйте:
set -- $(IFS=":"; echo "$PATH")
Это будет работать нормально, пока в $PATH нет пробелов.Заставить его работать для элементов пути, содержащих пробелы, — нетривиальное упражнение, оставленное заинтересованному читателю.Вероятно, с этим проще справиться, используя язык сценариев, такой как Perl.
У меня также есть сценарий, clnpath
, который я широко использую для настройки PATH.Я задокументировал это в ответе на "Как избежать дублирования переменной PATH в csh".
Что делает эту проблему раздражающей, так это корпуса столбов между первым и последним элементами.Проблему можно элегантно решить, изменив 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"
Вот однострочник Perl:
PATH=`perl -e '$a=shift;$_=$ENV{PATH};s#:$a(:)|^$a:|:$a$#$1#;print' /home/usr/bin`
А $a
переменная получает путь, который нужно удалить.А s
(заменитель) и print
команды неявно действуют на $_
переменная.
Хорошие вещи здесь.Я использую это, чтобы не добавлять обманщиков.
#!/bin/bash
#
######################################################################################
#
# Allows a list of additions to PATH with no dupes
#
# Patch code below into your $HOME/.bashrc file or where it
# will be seen at login.
#
# Can also be made executable and run as-is.
#
######################################################################################
# add2path=($HOME/bin .) ## uncomment space separated list
if [ $add2path ]; then ## skip if list empty or commented out
for nodup in ${add2path[*]}
do
case $PATH in ## case block thanks to MIKE511
$nodup:* | *:$nodup:* | *:$nodup ) ;; ## if found, do nothing
*) PATH=$PATH:$nodup ## else, add it to end of PATH or
esac ## *) PATH=$nodup:$PATH prepend to front
done
export PATH
fi
## debug add2path
echo
echo " PATH == $PATH"
echo
При включенном расширенном подстановке можно сделать следующее:
# delete all /opt/local paths in PATH
shopt -s extglob
printf "%s\n" "${PATH}" | tr ':' '\n' | nl
printf "%s\n" "${PATH//+(\/opt\/local\/)+([^:])?(:)/}" | tr ':' '\n' | nl
man bash | less -p extglob
Расширенная однострочная подстановка (ну, вроде):
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; }
Добавляя двоеточия в PATH, мы также могли бы сделать что-то вроде:
path_remove () {
declare i newPATH
# put a colon at the beginning & end AND double each colon in-between
newPATH=":${PATH//:/::}:"
for ((i=1; i<=${#@}; i++)); do
#echo ${@:${i}:1}
newPATH="${newPATH//:${@:${i}:1}:/}" # s/:\/fullpath://g
done
newPATH="${newPATH//::/:}"
newPATH="${newPATH#:}" # remove leading colon
newPATH="${newPATH%:}" # remove trailing colon
unset PATH
PATH="${newPATH}"
export PATH
return 0
}
path_remove_all () {
declare i newPATH extglobVar
extglobVar=0
# enable extended globbing if necessary
[[ ! $(shopt -q extglob) ]] && { shopt -s extglob; extglobVar=1; }
newPATH=":${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}" # s/:\/path[^:]*//g
done
newPATH="${newPATH#:}" # remove leading colon
newPATH="${newPATH%:}" # remove trailing colon
# disable extended globbing if it was enabled in this function
[[ $extglobVar -eq 1 ]] && shopt -u extglob
unset PATH
PATH="${newPATH}"
export PATH
return 0
}
path_remove /opt/local/bin /usr/local/bin
path_remove_all /opt/local /usr/local
В path_remove_all (по прокси):
-newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}"
+newPATH="${newPATH//:${@:${i}:1}*([^:])/}" # s/:\/path[^:]*//g
Хотя это очень старая тема, я подумал, что это решение может представлять интерес:
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
нашел это на этом Сообщение блога.Думаю, этот вариант мне нравится больше всего :)
Я применил несколько иной подход, чем большинство людей здесь, и сосредоточился конкретно на манипуляциях со строками, например:
path_remove () {
if [[ ":$PATH:" == *":$1:"* ]]; then
local dirs=":$PATH:"
dirs=${dirs/:$1:/:}
export PATH="$(__path_clean $dirs)"
fi
}
__path_clean () {
local dirs=${1%?}
echo ${dirs#?}
}
Выше приведен упрощенный пример последних функций, которые я использую.Я также создал path_add_before
и path_add_after
позволяя вам вставить путь до/после указанного пути, уже имеющегося в PATH.
Полный набор функций доступен в path_helpers.sh в моем точечные файлы.Они полностью поддерживают удаление/добавление/добавление/вставку в начале/середине/конце строки PATH.
Завершающий символ ':' вызван тем, что вы устанавливаете окончание строки, а не разделитель.Я использую модули с ограниченным ресурсом и предпочитаю упаковывать все в один скрипт, без этих странностей:
path_remove () {
PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '$0 != "'$1'"{print s _ $0;s=":"}')"
}