在Solaris 10 Bourne shell上进行错误替换

时间:2012-01-02 06:06:40

标签: shell

我需要在字符串中的最后一个opt之前提取部分字符串:

NDS=/opt/novell/opt/eDirectory/opt/abc

我只想要/opt/novell/opt/eDirectory/部分

我使用了NDSHOME=${NDS%opt*} 但我在Solaris 10上使用Bourne shell进行了错误的替换, 虽然这个脚本在Linux和AIX上运行良好。 有人可以找到解决方案??

4 个答案:

答案 0 :(得分:1)

dirname命令打印除了作为参数给出的路径名的最后一级以外的所有级别。

$ NDS=/opt/novell/opt/eDirectory/opt/abc
$ NDSHOME=`dirname $NDS`
$ echo $NDSHOME
/opt/novell/opt/eDirectory/opt

(根据需要添加export。)

编辑:

以上在这种情况下不起作用。 OP希望删除最后opt之后的路径的所有组件,而不仅仅是最后一个组件。我会留在这里,以防它对其他人有用。

可以在循环中使用dirname,当最后一个组件(由basename确定)是'opt'时停止:

NDSHOME="$NDS"
while [ "`basename $NDSHOME`" != opt ] ; do
    NDSHOME="`dirname $NDSHOME`"
done

但这比它需要的更复杂; sed是一个更好的解决方案。

SiegeX的答案很好,但它将opt视为字符串,而不仅仅是路径组件。例如,它将转为

/opt/novell/opt/eDirectory/opt/helicopter

/opt/novell/opt/eDirectory/opt/helic

试试这个:

NDSHOME=`echo "$NDS" | sed 's,\(.*\)/opt/.*$,\1,'`

(请注意,使用,而不是/作为分隔符,因此模式中的/字符不必转义。)

答案 1 :(得分:1)

Solaris绝对是POSIX(以及xpg4和susv3等几个相关标准),但它也非常重视与旧版本的兼容性。

副作用是当这两个功能以某种方式发生冲突时,默认情况下,受影响的命令不符合POSIX标准,不会破坏旧脚本。

如果您想要POSIX兼容性并且没有遗留脚本问题,只需将PATH设置为:

PATH=/usr/xpg6/bin:/usr/xpg4/bin:/usr/ccs/bin:$PATH

并将您的登录shell设置为/usr/xpg4/bin/sh

或者,如果您不需要严格遵守,则可以使用/bin/ksh作为默认shell。

对于Solaris 10及更早版本,您不应该在新脚本中使用/bin/sh

作为参考,这里是Solaris 10 standards手册页,Solaris 11的手册页是here

答案 2 :(得分:0)

改为使用Bourne-Again shell。

答案 3 :(得分:0)

Solaris'/ bin / sh众所周知不兼容Posix。

您可以使用sed

尝试以下解决方法
NDSHOME=`echo "$NDS" | sed 's/^\(.*\)\<opt\>.*$/\1/'`

注意: 通常情况下,我会使用$()代替backtics进行命令替换,但我认为这些也不适用于Solaris。

修改 更改了它,以便opt与字内边界不匹配

$ echo $NDS
/opt/novell/opt/eDirectory/opt/helicopter
$ echo "$NDS" | sed 's/^\(.*\)\<opt\>.*$/\1/'
/opt/novell/opt/eDirectory/