Solaris 10 Bourne shell上的错误替换

Solaris 10 Bourne shell上的错误替换,shell,Shell,我需要在字符串的最后一个选项之前提取部分字符串: NDS=/opt/novell/opt/eDirectory/opt/abc 我只想要/opt/novell/opt/eDirectory/部分 我使用了NDSHOME=${NDS%opt*} 但我在Solaris 10上得到了糟糕的替代,即使用Bourne shell, 尽管此脚本在Linux和AIX上运行良好。 有人能找到解决方案吗?再次使用Bourne外壳。Solaris'/bin/sh不兼容Posix是出了名的 您可以使用sed NDS

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

NDS=/opt/novell/opt/eDirectory/opt/abc
我只想要
/opt/novell/opt/eDirectory/
部分

我使用了
NDSHOME=${NDS%opt*}
但我在Solaris 10上得到了糟糕的替代,即使用Bourne shell, 尽管此脚本在Linux和AIX上运行良好。
有人能找到解决方案吗?

再次使用Bourne外壳。

Solaris'/bin/sh不兼容Posix是出了名的

您可以使用
sed

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

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

$ NDS=/opt/novell/opt/eDirectory/opt/abc
$ NDSHOME=`dirname $NDS`
$ echo $NDSHOME
/opt/novell/opt/eDirectory/opt
(根据需要添加
导出
。)

编辑:

在这种情况下,上述方法不起作用。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
进入

试试这个:

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

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

Solaris肯定与POSIX(以及一些相关标准,如xpg4和susv3)兼容,但它也非常重视与旧版本的兼容性

副作用是,当这两个特性以某种方式冲突时,默认情况下,受影响的命令与POSIX不兼容,因此不会破坏遗留脚本

如果您想要POSIX兼容性并且没有遗留脚本问题,只需按如下方式设置路径:

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手册页,Solaris 11手册页是。

我们没有更改shell的选项,只能使用bourne shell。那么您就是SOL了。使用
sed
或类似方法。他需要
dirname
两次才能获得他想要的输出。在这种情况下,不确定opt之后是否只有一到两个级别。。它可以是任意数量的级别。因此,我们不能使用dirname。Solaris上的
/bin/sh
命令是一个真正的(SystemV)Bourne Shell。你应该考虑使用KORN Shell(甚至BASH)。你应该写“Solaris/BIN/SH是臭名昭著的……”。Solaris本身绝对符合POSIX。@jlliagre足够公平,已更改。
NDSHOME=`echo "$NDS" | sed 's,\(.*\)/opt/.*$,\1,'`
PATH=/usr/xpg6/bin:/usr/xpg4/bin:/usr/ccs/bin:$PATH