我正在使用适用于 Linux 和 Solaris (Nexenta) 的脚本。
此行适用于 Linux,但不适用于 Solaris(但当从 shell 运行时,它可以工作):
cat "pg_hba.conf" | sed "0,/^local/{s/md5/trust/}"
错误信息是:
sed: command garbled: 0,/^local/{s/md5/trust/}
经过一番研究,我发现sed
bash 在脚本中使用的是不同的。
来自外壳:/usr/bin/sed
来自脚本:/usr/sun/bin/sed
我想让脚本使用/usr/bin/sed
.
我尝试做的事情:
sed
使用完整路径进行调用。结果相同。看来还是用其他的sed
...- 尝试通过 调用它
bash -l
。结果相同。 - 试图声明一个不同的命令:
S=/usr/lib/sed
并使用$S
。结果相同。 - 检查 PATH - cmd 和脚本都
/usr/bin
在其中。 - 尝试将双引号替换为单引号。结果相同。
尝试使用 -r 标志运行 sed 。输出是:
# /usr/xpg4/bin/sed -r /usr/xpg4/bin/sed: illegal option -- r Usage: sed [-n] script [file...] sed [-n] [-e script]...[-f script_file]...[file...]
帮助??
我需要做的是将第一行以“local”开头的“md5”的第一个匹配项替换为“trust”)。我知道我可以这样做,但我这个sed
问题太让我痒了!
编辑:
我希望这能带来一些订单......
- 登录 shell 的路径 =
/usr/local/ctera/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/ctera/apache-ant-1.8.2/bin
- 脚本中的路径 =
/usr/sbin:/usr/bin:/usr/local/ctera/apache-ant-1.8.2/bin:/usr/local/ctera/apache-ant-1.8.2/bin
PATH=$(command -p getconf PATH):$PATH
调用 时脚本中的 PATH =/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin:/usr/bin:/usr/local/ctera/apache-ant-1.8.2/bin:/usr/local/ctera/apache-ant-1.8.2/bin
truss -f sed
来自登录 shell 调用/usr/bin/sed
truss -f sed
来自脚本调用/usr/sun/bin/sed
truss -f /usr/bin/sed
来自脚本调用/usr/sun/bin/sed
!!!- 设置后
PATH=$(command -p getconf PATH):$PATH
:
7.1truss -f sed
来自脚本调用/usr/xpg4/bin/sed
7.2truss -f /usr/bin/sed
来自脚本调用/usr/sun/bin/sed
!
更多信息:
命令输出:(从 shell 提示符和脚本内运行)
truss -ft execve /usr/bin/sed q
作为 shell 命令:
8604: execve("/usr/bin/sed", 0x08047D20, 0x08047D2C) argc = 2
来自脚本:
8545: execve("/usr/sun/bin/sed", 0x08047768, 0x08047774) argc = 2
file /usr/bin/sed
作为 shell 命令:
/usr/bin/sed: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), stripped
来自脚本:
file: /usr/bin/sed zero size or zero entry ELF section - ELF capabilities ignored file: /usr/bin/sed: can't read ELF header /usr/bin/sed: data
ls -l /usr/bin/sed
作为 shell 命令:
-rwxr-xr-x 1 root root 96440 May 31 2008 /usr/bin/sed
来自脚本:
-rwxr-xr-x 1 root root 96440 May 31 2008 /usr/bin/sed
ls -ld $(type -pa sed)
作为 shell 命令:
-rwxr-xr-x 1 root root 96440 May 31 2008 /bin/sed -rwxr-xr-x 1 root root 96440 May 31 2008 /usr/bin/sed
来自脚本:
-rwxr-xr-x 1 root root 96440 May 31 2008 /usr/bin/sed
md5sum $(type -pa sed)
作为 shell 命令:
385361c5111226c8eac8e25b53fed29c /bin/sed 385361c5111226c8eac8e25b53fed29c /usr/bin/sed
来自脚本:
385361c5111226c8eac8e25b53fed29c /usr/bin/sed
该脚本由JAVA代码调用。
uname -a
SunOS cteraportal 5.11 NexentaOS_134f i86pc i386 i86pc Solaris
这可能会添加有关
sed
我的计算机上的版本的信息~# ll `find / -name sed` -rwxr-xr-x 1 root root 96440 May 31 2008 /usr/bin/sed -r-xr-xr-x 1 root bin 35656 Sep 7 2010 /usr/sun/bin/sed -r-xr-xr-x 1 root bin 32104 Sep 7 2010 /usr/ucb/sed -r-xr-xr-x 1 root bin 35636 Sep 7 2010 /usr/xpg4/bin/sed /usr/share/doc/sed: total 113 -rw-r--r-- 1 root root 168 Jun 21 2005 AUTHORS.gz -rw-r--r-- 1 root root 2507 Jun 21 2005 BUGS.gz -rw-r--r-- 1 root root 6584 Feb 3 2006 NEWS.gz -rw-r--r-- 1 root root 285 Jun 21 2005 README.gz -rw-r--r-- 1 root root 1071 Jan 12 2006 THANKS.gz -rw-r--r-- 1 root root 4806 May 31 2008 changelog.Debian.gz -rw-r--r-- 1 root root 32312 Feb 3 2006 changelog.gz -rw-r--r-- 1 root root 796 May 31 2008 copyright drwxr-xr-x 2 root root 3 May 30 2011 examples drwxr-xr-x 2 root root 3 May 30 2011 sed-4.1.5 -rw-r--r-- 1 root root 56538 May 31 2008 sedfaq.txt.gz
答案1
好的,找到了。现在这是有道理的。
该行为是 Nexenta 特有的,解释于http://lwn.net/Articles/334756/
GNU 而非 GNU
Nexenta 的默认行为是更喜欢 GNU 实用程序,这些实用程序安装在
/usr/bin
等/usr/sbin
中。这些实用程序的 Sun 版本安装在/usr/sun/bin
和中/usr/sun/sbin
。 Nexenta 使用一种技巧能够在 GNU 和 SUN 个性之间切换:如果环境变量 SUN_PERSONALITY 设置为 1,则搜索路径/usr/sun/bin
和/usr/sun/sbin
优先,即使用户通过其绝对路径显式执行命令,例如/usr/bin/sed
。这可确保基于 Solaris 的脚本无需修改即可在 Nexenta 中运行。 Nexenta 还在其 SVR4 包命令中使用此功能。它们可用于安装 SVR4 格式的本机 Solaris 软件包,调用 Alien 将软件包即时转换为 Debian 软件包。
这是在 libc 中的某个地方完成的。
所以,
$ sed --version
GNU sed version 4.1.5
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.
$ SUN_PERSONALITY=1 sed --version
sed: illegal option -- version
因此,您的脚本从 Java 开始,必须设置 SUN_PERSONALITY。
如果您需要 GNU 工具,您可以在脚本中取消设置。
答案2
任何状况之下,
sed "0,/^local/{s/md5/trust/}"
是 GNU 特定的(地址和之前0
缺失的部分)并且不能与任何其他实现一起使用(默认情况下Solaris 不随 GNU 一起提供)。;
}
sed
sed
便携/标准:
sed '/^local/,$!s/md5/trust/'
仅替换直到(但不包括)以 开头的第一个行local
。或者:
awk 'NR == 1, /^local/ {gsub(/md5/,"trust")}; {print}'
(在 Solaris 上,您可能需要command -p awk
)。
如果您想在匹配的第一行进行替换/^local/
:
awk '/^local/ && ! seen {gsub(/md5/, "trust"); seen = 1}; {print}'
或者:
sed -e '/^local/!b' -e 's/md5/trust/g;:1' -e 'n;b1'
为了确保在 Solaris 和 Linux 中获得符合 POSIX 标准的实用程序(从 POSIX shell,如bash
或ksh
(或/usr/xpg4/bin/sh
在 Solaris 上)),您可以添加:
PATH=$(command -p getconf PATH):$PATH
到脚本的顶部。或者command -p
在您想要 POSIX 版本的每个命令前面添加。
答案3
这是另一种便携式方法sed
:
sed 1i\\ file |
sed '1,/^local/s/md5/trust/;1d'
给自己一点喘息的空间。这会在文件的开头插入一个空行,这样您就可以依赖一两个东西。
你也可以这样做:
{ echo; cat file; } |
sed '1,/^local/s/md5/trust/;1d'