Что самый изящный путь состоит в том, чтобы удалить путь из переменной $PATH в Bash?

Примечание: использование неопределенной константы XXX - предполагается, что «XXX»

, или в PHP 7.2 или новее:

Предупреждение: использование неопределенной константы XXX - предполагаемый «XXX» ( это вызовет ошибку в будущей версии PHP)

Это уведомление возникает, когда токен используется в коде и представляется константой, но константа с этим именем не определена.

Одной из наиболее распространенных причин этого уведомления является отказ от цитирования строки, используемой в качестве ассоциативного массива.

Например:

// Wrong
echo $array[key];

// Right
echo $array['key'];

Другие распространенные причины отсутствует значок $ (доллар) перед именем переменной:

// Wrong
echo varName;

// Right
echo $varName;

Или, может быть, у вас есть некорректная другая константа или ключевое слово:

// Wrong
$foo = fasle;

// Right
$foo = false;

Он также может быть признаком того, что необходимое расширение или библиотека PHP отсутствует при попытке доступа к константе, определенной этой библиотекой.

Вопросы, относящиеся:

106
задан cxw 24 April 2019 в 16:16
поделиться

16 ответов

Минута с 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/:*$//')

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

47
ответ дан Dougal 24 November 2019 в 03:49
поделиться

Так как это имеет тенденцию быть довольно проблематичным, поскольку там НЕ изящный путь, я рекомендую избежать проблемы путем реконструкции решения: создайте свой ПУТЬ, а не попытайтесь разъединить его.

я мог быть более конкретным, если бы я знал Ваш контекст настоящей проблемы. Тем временем я буду использовать сборку программного обеспечения в качестве контекста.

типичная проблема А со сборками программного обеспечения состоит в том, что это повреждается на некоторых машинах, в конечном счете из-за того, как кто-то настроил их оболочку по умолчанию (ПУТЬ и другие переменные среды). Изящное решение состоит в том, чтобы сделать Ваши сценарии сборки неуязвимыми, полностью определив среду оболочки. Кодируйте свои сценарии сборки для устанавливания ПУТИ и других переменных среды на основе собирающихся частей, что Вы управляете, такие как местоположение компилятора, библиотек, инструментов, компонентов, и т.д. Делаете каждый настраиваемый объект чем-то, что можно индивидуально установить, проверить, и затем использовать соответственно в сценарии.

, Например, у меня есть Основанная на знатоке WebLogic-целенаправленная сборка Java, которую я наследовал в своем новом работодателе. Сценарий сборки известен за то, что был хрупок, и другой новый сотрудник, и я провел три недели (не полный рабочий день, просто тут и там, но все еще много часов) то, чтобы заставлять его работать над нашими машинами. Существенный шаг был то, что я взял под свой контроль ПУТЬ так, чтобы я знал точно, какой Java, который Знаток, и который вызывался WebLogic. Я создал переменные среды для указания на каждый из тех инструментов, тогда я вычислил ПУТЬ на основе тех плюс немногие другие. Подобные методы приручили другие конфигурируемые параметры, пока мы наконец не создали восстанавливаемую сборку.

Между прочим, не используйте Знатока, Java хорошо, и только купите WebLogic при абсолютной необходимости в его кластеризации (но иначе не, и особенно не его собственные функции).

С наилучшими пожеланиями.

0
ответ дан Rob Williams 24 November 2019 в 03:49
поделиться

Как с @litb, я внес ответ на вопрос" , Как я управляю элементами $PATH в сценариях оболочки ", таким образом, мой основной ответ там.

функциональность 'разделения' в bash и другие производные Оболочки Bourne наиболее аккуратно достигается с $IFS, межразделитель полей. Например, для установки позиционных параметров ($1, $2...) к элементам ПУТИ, используйте:

set -- $(IFS=":"; echo "$PATH")

Это будет работать хорошо, пока нет никаких пробелов в $PATH. Создание его работать на элементы пути, содержащие пробелы, является нетривиальным осуществлением - уехал в заинтересованного читателя. Вероятно, более просто иметь дело с ним с помощью языка сценариев, такого как Perl.

у меня также есть сценарий, clnpath, который я использую экстенсивно для того, чтобы установить мой ПУТЬ. Я зарегистрировал его в ответе на" , Как удержаться от дублирования переменной ПУТИ в csh".

0
ответ дан Community 24 November 2019 в 03:49
поделиться

Мой грязный взлом:

echo ${PATH} > t1
vi t1
export PATH=$(cat t1)
51
ответ дан Martin York 24 November 2019 в 03:49
поделиться

Вот простое решение, которое я могу создать:

#!/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" для удаления просто того элемента.

обновление на sschuberth

Даже при том, что я думаю пробелы в $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[*]}"
26
ответ дан Community 24 November 2019 в 03:49
поделиться

Ну, в ударе, поскольку это поддерживает регулярное выражение, я просто сделал бы:

PATH=${PATH/:\/home\/user\/bin/}
3
ответ дан mat 24 November 2019 в 03:49
поделиться

Что делает эту проблему раздражающей, fencepost случаи среди первых и последних элементов. Проблема может быть изящно решена путем изменения 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
ответ дан Norman Ramsey 24 November 2019 в 03:49
поделиться

Вот острота Perl:

PATH=`perl -e '$a=shift;$_=$ENV{PATH};s#:$a(:)|^$a:|:$a$#$1#;print' /home/usr/bin`

$a переменная заставляет путь быть удаленным. s (замена) и print команды неявно воздействуют на $_ переменная.

0
ответ дан J. A. Faucett 24 November 2019 в 03:49
поделиться

Я действительно писал ответ на это здесь (использующий 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:

Так или иначе, для того же вопроса и большого количества полезных ответов, посмотрите здесь.

4
ответ дан Community 24 November 2019 в 03:49
поделиться

Хорошо здесь. Я использую это, чтобы сохранить из добавления дупсов в первую очередь.

#!/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
0
ответ дан 24 November 2019 в 03:49
поделиться

Расширенные глобубские одноклассники (ну, вроде):

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
ответ дан 24 November 2019 в 03:49
поделиться

При включенной функции расширенного глобуса можно сделать следующее:

# 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
0
ответ дан 24 November 2019 в 03:49
поделиться

Так как большая проблема с заменой является конечные случаи, как насчет заключения конечных случаев ничем не отличается от других случаев? Если бы путь уже имел двоеточия в начале и конце, мы могли бы просто найти нашу желаемую строку, завернутую с двоеточиями. Как это так, мы можем легко добавить эти двоеточия и удалить их потом.

# 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

Чистый Bash :).

40
ответ дан 24 November 2019 в 03:49
поделиться

Да, например, в конце пути в конце пути делает удаление пути немного менее неуклюжему и ошибку.

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 
1
ответ дан 24 November 2019 в 03:49
поделиться

Добавление двоиков к пути мы могли бы Также сделать что-то вроде:

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 
0
ответ дан 24 November 2019 в 03:49
поделиться

в path_remove_all (proxxy):

-newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}" 
+newPATH="${newPATH//:${@:${i}:1}*([^:])/}"        # s/:\/path[^:]*//g 
0
ответ дан 24 November 2019 в 03:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: