Unix 如何在shell脚本中操作$PATH元素?
有没有一种惯用的方法可以从类似路径的shell变量中删除元素 这就是我想要的Unix 如何在shell脚本中操作$PATH元素?,unix,shell,idioms,path-variables,Unix,Shell,Idioms,Path Variables,有没有一种惯用的方法可以从类似路径的shell变量中删除元素 这就是我想要的 PATH=/home/joe/bin:/usr/local/bin:/usr/bin:/bin:/path/to/app/bin:. 和删除或替换/path/to/app/bin,而不破坏变量的其余部分。允许我在任意位置放置新元素的额外点。目标将由定义良好的字符串识别,并且可能出现在列表中的任何点 我知道我已经看到了这一点,也许我可以自己拼凑一些东西,但我正在寻找一个很好的方法。可移植性和标准化优先 我使用bash,
PATH=/home/joe/bin:/usr/local/bin:/usr/bin:/bin:/path/to/app/bin:.
和删除或替换/path/to/app/bin
,而不破坏变量的其余部分。允许我在任意位置放置新元素的额外点。目标将由定义良好的字符串识别,并且可能出现在列表中的任何点
我知道我已经看到了这一点,也许我可以自己拼凑一些东西,但我正在寻找一个很好的方法。可移植性和标准化优先
我使用bash,但在您最喜欢的shell中也欢迎使用示例
这里的上下文是需要在一个大型科学分析包的多个版本(一个用于分析,另一个用于处理框架)之间方便地切换,该分析包生成几十个可执行文件,在文件系统中存储数据,并使用环境变量帮助查找所有这些内容。我想编写一个脚本来选择一个版本,并且需要能够删除与当前活动版本相关的
$PATH
元素,并用与新版本相关的相同元素替换它们
这与在重新运行登录脚本等时防止重复的
$PATH
元素有关
- 先前的类似问题:
- 随后的类似问题:
#!/bin/bash
NEW_PATH=$(echo -n $PATH | tr ":" "\n" | sed "/foo/d" | tr "\n" ":")
export PATH=$NEW_PATH
将从路径中删除包含“foo”的路径
您还可以使用sed在给定行之前或之后插入新行
编辑:可以通过排序和uniq管道删除重复项:
echo -n $PATH | tr ":" "\n" | sort | uniq -c | sed -n "/ 1 / s/.*1 \(.*\)/\1/p" | sed "/foo/d" | tr "\n" ":"
第一件突然出现在我脑海中改变字符串的一部分的事情是sed替换 例如: 如果echo$PATH=>“/usr/pkg/bin:/usr/bin:/bin:/usr/pkg/games:/usr/pkg/X11R6/bin” 然后将“/usr/bin”更改为“/usr/local/bin”可以这样做:
# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace-path PATH $PATH /exact/path/to/remove
# replace-path-pattern PATH $PATH <grep pattern for target path>
#
# To replace a path:
# replace-path PATH $PATH /exact/path/to/remove /replacement/path
# replace-path-pattern PATH $PATH <target pattern> /replacement/path
#
###############################################################################
# Finds the _first_ list element matching $2
#
# $1 name of a shell variable to be set
# $2 name of a variable with a path-like structure
# $3 a grep pattern to match the desired element of $1
function path-element-by-pattern (){
target=$1;
list=$2;
pat=$3;
export $target=$(echo -n $list | tr ":" "\n" | grep -m 1 $pat);
return
}
# Removes or replaces an element of $1
#
# $1 name of the shell variable to set (i.e. PATH)
# $2 a ":" delimited list to work from (i.e. $PATH)
# $2 the precise string to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace-path () {
path=$1;
list=$2;
removestr=$3;
replacestr=$4; # Allowed to be ""
export $path=$(echo -n $list | tr ":" "\n" | sed "s|$removestr|$replacestr|" | tr "\n" ":" | sed "s|::|:|g");
unset removestr
return
}
# Removes or replaces an element of $1
#
# $1 name of the shell variable to set (i.e. PATH)
# $2 a ":" delimited list to work from (i.e. $PATH)
# $2 a grep pattern identifying the element to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace-path-pattern () {
path=$1;
list=$2;
removepat=$3;
replacestr=$4; # Allowed to be ""
path-element-by-pattern removestr $list $removepat;
replace-path $path $list $removestr $replacestr;
}
echo $PATH | awk -F: -f rem_dup.awk | paste -sd:
##生成标准输出文件
##使用“=”字符代替斜杠(“/”),因为这样会很混乱,
#路径中不可能有替代引用字符
##路径分隔符“:”在此处被删除并重新添加,
#在最后一个路径后可能需要额外的冒号
echo$PATH | sed'=/usr/bin:=/usr/local/bin:='
此解决方案替换整个path元素,所以若新元素相似,则可能是多余的
如果新路径'-s不是动态的,但始终在某个常量集内,则可以将其保存在变量中,并根据需要分配:
路径=$TEMP_PATH_1;
#命令\N
路径=$TEMP_PATH_2;
#命令等
可能不是你想的那样。bash/unix上的一些相关命令是:
推动
邻苯二胺
光盘
对于单柱,ls#可能为l-1A;
找到
格雷普
这可以证实你认为文件是从哪里来的;
环境
类型
..所有这些和更多都对路径或目录有一些影响。文本更改部分可以通过多种方式完成
选择的任何解决方案都有4个部分:
1) 按原样获取路径
2) 解码路径以找到需要更改的零件
3) 确定需要哪些变更/整合这些变更
4) 验证/最终积分/设置变量在对“”的回答中有两个相关程序。他们更专注于确保没有重复的元素,但我提供的脚本可以用作:
export PATH=$(clnpath $head_dirs:$PATH:$tail_dirs $remove_dirs)
假设$head\u dirs中有一个或多个目录,$tail\u dirs中有一个或多个目录,$remove\u dirs中有一个或多个目录,那么它使用shell将head、current和tail部分连接成一个大值,然后从结果中删除$remove\u dirs中列出的每个目录(如果不存在,则不是错误),以及消除路径中任何目录的第二次和后续出现
这不涉及将路径组件放置到特定位置(除了在开始或结束位置,以及仅间接放置的位置)。注意,指定要添加新元素的位置或要替换的元素很麻烦。好的,感谢所有响应者。我已经准备了florin答案的封装版本。第一步如下所示:
# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace-path PATH $PATH /exact/path/to/remove
# replace-path-pattern PATH $PATH <grep pattern for target path>
#
# To replace a path:
# replace-path PATH $PATH /exact/path/to/remove /replacement/path
# replace-path-pattern PATH $PATH <target pattern> /replacement/path
#
###############################################################################
# Finds the _first_ list element matching $2
#
# $1 name of a shell variable to be set
# $2 name of a variable with a path-like structure
# $3 a grep pattern to match the desired element of $1
function path-element-by-pattern (){
target=$1;
list=$2;
pat=$3;
export $target=$(echo -n $list | tr ":" "\n" | grep -m 1 $pat);
return
}
# Removes or replaces an element of $1
#
# $1 name of the shell variable to set (i.e. PATH)
# $2 a ":" delimited list to work from (i.e. $PATH)
# $2 the precise string to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace-path () {
path=$1;
list=$2;
removestr=$3;
replacestr=$4; # Allowed to be ""
export $path=$(echo -n $list | tr ":" "\n" | sed "s|$removestr|$replacestr|" | tr "\n" ":" | sed "s|::|:|g");
unset removestr
return
}
# Removes or replaces an element of $1
#
# $1 name of the shell variable to set (i.e. PATH)
# $2 a ":" delimited list to work from (i.e. $PATH)
# $2 a grep pattern identifying the element to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace-path-pattern () {
path=$1;
list=$2;
removepat=$3;
replacestr=$4; # Allowed to be ""
path-element-by-pattern removestr $list $removepat;
replace-path $path $list $removestr $replacestr;
}
echo $PATH | awk -F: -f rem_dup.awk | paste -sd:
#path_tools.bash
#
#一组用于操作“:”分隔列表的工具,如
#规范$PATH变量。
#
#/bin/sh可以通过替换$()重新获得兼容性
#使用``样式设置命令扩展的样式
###############################################################################
#用法:
#
#要删除路径,请执行以下操作:
#替换路径路径$path/exact/path/to/remove
#替换路径模式path$path
#
#要替换路径,请执行以下操作:
#替换路径路径$path/exact/path/to/remove/replacement/path
#替换路径模式路径$path/replacement/path
#
###############################################################################
#查找与$2匹配的_first_uu列表元素
#
#$1要设置的shell变量的名称
#$2具有类似路径结构的变量的名称
#$3匹配所需元素$1的grep模式
模式()的函数路径元素{
目标=1美元;
名单=$2;
pat=3美元;
export$target=$(echo-n$list | tr:“\n”| grep-m1$pat);
返回
}
#删除或替换$1的元素
#
#$1要设置的shell变量的名称(即路径)
#$2A“:”要从中工作的分隔列表(即$PATH)
#$2要移除/替换的精确字符串
#$3替换字符串(使用“”删除)
函数替换路径(){
路径=$1;
名单=$2;
Removest=3美元;
replacestr=$4;#允许为“”
export$path=$(echo-n$list | tr:“\n”sed“s”|$removestr |$replacestr |“| tr”\n:“| sed”s |:::|:| g”);
未设定再投资
返回
}
#删除或替换$1的元素
#
#$1外壳的名称
PATH=/bin::/usr/local/bin
export $target=$(echo -n $list | tr ":" "\n" | grep -m 1 "^$pat\$")
# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace_path PATH $PATH /exact/path/to/remove
# replace_path_pattern PATH $PATH <grep pattern for target path>
#
# To replace a path:
# replace_path PATH $PATH /exact/path/to/remove /replacement/path
# replace_path_pattern PATH $PATH <target pattern> /replacement/path
#
###############################################################################
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 a ":" delimited list to work from (e.g. $PATH)
# $3 the precise string to be removed/replaced
# $4 the replacement string (use "" for removal)
function replace_path () {
path=$1
list=$2
remove=$3
replace=$4 # Allowed to be empty or unset
export $path=$(echo "$list" | tr ":" "\n" | sed "s:^$remove\$:$replace:" |
tr "\n" ":" | sed 's|:$||')
}
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 a ":" delimited list to work from (e.g. $PATH)
# $3 a grep pattern identifying the element to be removed/replaced
# $4 the replacement string (use "" for removal)
function replace_path_pattern () {
path=$1
list=$2
removepat=$3
replacestr=$4 # Allowed to be empty or unset
removestr=$(echo "$list" | tr ":" "\n" | grep -m 1 "^$removepat\$")
replace_path "$path" "$list" "$removestr" "$replacestr"
}
#!/usr/bin/perl -w
#
# "@(#)$Id: echopath.pl,v 1.7 1998/09/15 03:16:36 jleffler Exp $"
#
# Print the components of a PATH variable one per line.
# If there are no colons in the arguments, assume that they are
# the names of environment variables.
@ARGV = $ENV{PATH} unless @ARGV;
foreach $arg (@ARGV)
{
$var = $arg;
$var = $ENV{$arg} if $arg =~ /^[A-Za-z_][A-Za-z_0-9]*$/;
$var = $arg unless $var;
@lst = split /:/, $var;
foreach $val (@lst)
{
print "$val\n";
}
}
echo
xpath=$PATH
replace_path xpath $xpath /usr
echopath $xpath
echo
xpath=$PATH
replace_path_pattern xpath $xpath /usr/bin /work/bin
echopath xpath
echo
xpath=$PATH
replace_path_pattern xpath $xpath "/usr/.*/bin" /work/bin
echopath xpath
.
/Users/jleffler/bin
/usr/local/postgresql/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/usr/bin
/bin
/sw/bin
/usr/sbin
/sbin
.
/Users/jleffler/bin
/usr/local/postgresql/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/work/bin
/bin
/sw/bin
/usr/sbin
/sbin
.
/Users/jleffler/bin
/work/bin
/usr/local/mysql/bin
/Users/jleffler/perl/v5.10.0/bin
/usr/local/bin
/usr/bin
/bin
/sw/bin
/usr/sbin
/sbin
replace_path PATH /usr/bin /work/bin
list=$(eval echo '$'$path)
# path_tools.bash
#
# A set of tools for manipulating ":" separated lists like the
# canonical $PATH variable.
#
# /bin/sh compatibility can probably be regained by replacing $( )
# style command expansion with ` ` style
###############################################################################
# Usage:
#
# To remove a path:
# replace_path PATH /exact/path/to/remove
# replace_path_pattern PATH <grep pattern for target path>
#
# To replace a path:
# replace_path PATH /exact/path/to/remove /replacement/path
# replace_path_pattern PATH <target pattern> /replacement/path
#
###############################################################################
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 the precise string to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace_path () {
path=$1
list=$(eval echo '$'$path)
remove=$2
replace=$3 # Allowed to be empty or unset
export $path=$(echo "$list" | tr ":" "\n" | sed "s:^$remove\$:$replace:" |
tr "\n" ":" | sed 's|:$||')
}
# Remove or replace an element of $1
#
# $1 name of the shell variable to set (e.g. PATH)
# $2 a grep pattern identifying the element to be removed/replaced
# $3 the replacement string (use "" for removal)
function replace_path_pattern () {
path=$1
list=$(eval echo '$'$path)
removepat=$2
replacestr=$3 # Allowed to be empty or unset
removestr=$(echo "$list" | tr ":" "\n" | grep -m 1 "^$removepat\$")
replace_path "$path" "$removestr" "$replacestr"
}
echo
xpath=$PATH
replace_path xpath /usr
echopath xpath
echo
xpath=$PATH
replace_path_pattern xpath /usr/bin /work/bin
echopath xpath
echo
xpath=$PATH
replace_path_pattern xpath "/usr/.*/bin" /work/bin
echopath xpath
{
for(i=1;i<=NF;i++)
if($i == REM)
if(REP)
print REP;
else
continue;
else
print $i;
}
function path_repl {
echo $PATH | awk -F: -f rem.awk REM="$1" REP="$2" | paste -sd:
}
$ echo $PATH
/bin:/usr/bin:/home/js/usr/bin
$ path_repl /bin /baz
/baz:/usr/bin:/home/js/usr/bin
$ path_repl /bin
/usr/bin:/home/js/usr/bin
{
if(IDX < 1) IDX = NF + IDX + 1
for(i = 1; i <= NF; i++) {
if(IDX == i)
print REP
print $i
}
if(IDX == NF + 1)
print REP
}
function path_app {
echo $PATH | awk -F: -f app.awk REP="$1" IDX="$2" | paste -sd:
}
$ echo $PATH
/bin:/usr/bin:/home/js/usr/bin
$ path_app /baz 0
/bin:/usr/bin:/home/js/usr/bin:/baz
$ path_app /baz -1
/bin:/usr/bin:/baz:/home/js/usr/bin
$ path_app /baz 1
/baz:/bin:/usr/bin:/home/js/usr/bin
{
for(i = 1; i <= NF; i++) {
if(!used[$i]) {
print $i
used[$i] = 1
}
}
}
echo $PATH | awk -F: -f rem_dup.awk | paste -sd:
echo -n $PATH | xargs -d: stat -c %n
echo -n $PATH | xargs -d: -n1 test -d
#!/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=$(IFS=':';t=($PATH);unset IFS;t=(${t[@]%%*usr*});IFS=':';echo "${t[*]}");
echo $PATH
/usr/lib/jvm/java-1.6.0/bin:lib/jvm/java-1.6.0/bin/:/lib/jvm/java-1.6.0/bin/:/usr/lib/qt-3.3/bin:/usr/lib/ccache:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/tvnadeesh/bin
export PATH=$(echo $PATH | sed 's/\/lib\/jvm\/java-1.6.0\/bin\/://g')
function __path_add(){
if [ -d "$1" ] ; then
local D=":${PATH}:";
[ "${D/:$1:/:}" == "$D" ] && PATH="$PATH:$1";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
fi
}
function __path_remove(){
local D=":${PATH}:";
[ "${D/:$1:/:}" != "$D" ] && PATH="${D/:$1:/:}";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
}
# Just for the shake of completeness
function __path_replace(){
if [ -d "$2" ] ; then
local D=":${PATH}:";
if [ "${D/:$1:/:}" != "$D" ] ; then
PATH="${D/:$1:/:$2:}";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
fi
fi
}
ld_library_path=${ORACLE_HOME}/lib
LD_LIBRARY_PATH=${LD_LIBRARY_PATH//${ld_library_path}?(:)/}
export LD_LIBRARY_PATH=${ld_library_path}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
# add it to the path
PATH=~/bin/:$PATH:~/bin
export PATH=$(ruby -e 'puts ENV["PATH"].split(/:/).uniq.join(":")')
mungepath() {
export PATH=$(ruby -e 'puts ENV["PATH"].split(/:/).uniq.join(":")')
}