编辑:

编辑:

我正在使用适用于 Linux 和 Solaris (Nexenta) 的脚本。

此行适用于 Linux,但不适用于 Solaris(但当从 shell 运行时,它可以工作):

cat "pg_hba.conf" | sed "0,/^local/{s/md5/trust/}"

错误信息是:

sed: command garbled: 0,/^local/{s/md5/trust/}

经过一番研究,我发现sedbash 在脚本中使用的是不同的。

来自外壳:/usr/bin/sed

来自脚本:/usr/sun/bin/sed

我想让脚本使用/usr/bin/sed.

我尝试做的事情:

  1. sed使用完整路径进行调用。结果相同。看来还是用其他的sed...
  2. 尝试通过 调用它bash -l。结果相同。
  3. 试图声明一个不同的命令:S=/usr/lib/sed并使用$S。结果相同。
  4. 检查 PATH - cmd 和脚本都/usr/bin在其中。
  5. 尝试将双引号替换为单引号。结果相同。
  6. 尝试使用 -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问题太让我痒了!

编辑:

我希望这能带来一些订单......

  1. 登录 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
  2. 脚本中的路径 =
    /usr/sbin:/usr/bin:/usr/local/ctera/apache-ant-1.8.2/bin:/usr/local/ctera/apache-ant-1.8.2/bin
  3. 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
  4. truss -f sed来自登录 shell 调用/usr/bin/sed
  5. truss -f sed来自脚本调用/usr/sun/bin/sed
  6. truss -f /usr/bin/sed来自脚本调用/usr/sun/bin/sed!!!
  7. 设置后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 提示符和脚本内运行)

  1. 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

  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

  3. 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

  4. 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

  5. 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 一起提供)。;}sedsed

便携/标准:

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,如bashksh(或/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'

相关内容