【问题标题】:sed unknown option to `s' in bash script [duplicate]sed bash脚本中“s”的未知选项[重复]
【发布时间】:2014-09-02 13:07:03
【问题描述】:

我在整理我正在处理的 bash 脚本时遇到了一些麻烦

这是我正在使用的代码。

cat /crawler/bc_daemon.php | sed "s/PORT2/${PORT}/ig" | sed 's/IP2/IPADDRESS/ig' | \
   sed 's/USER2/USER/ig' | sed 's/PASS2/PASSWORD/ig' > bc_daemon.php

cat /crawler/bc_layout.php | sed "s/GITHUB/${REPO}/ig" | sed "s/COINNAME/${NAME}/ig" > bc_layout.php

奇怪的是这些行在脚本之外单独工作。但是当在脚本里面我得到这个

sed: -e expression #1, char 17: unknown option to `s'

当它可以按字面意思理解时我使用'',当它需要打印变量时使用""

在我看来这应该有效。但我不知道我的错误在哪里

【问题讨论】:

  • 我假设REPO 中有斜线,这会过早终止您的s/// 命令。尝试使用不同的分隔符 s!!!s@@@ 或不会出现在 REPO 值中的其他分隔符。
  • 仅供参考,BashFAQ #21 建议进行替换的方法没有 sed 要求内容中不存在的分隔符的限制。见mywiki.wooledge.org/BashFAQ/021
  • @Etan Reisner 就是这样。非常感谢。没想到 REPO 是一个 url,所以里面有 /。谢谢大家的帮助:)

标签: bash sed


【解决方案1】:

试试

cat /crawler/bc_layout.php | \
sed "s/GITHUB/${REPO}/gI" | \
sed "s/COINNAME/${NAME}/gI" > bc_layout.php

【讨论】:

    【解决方案2】:

    一种可能的情况是i 可能无法被您使用的sed 识别,您别无选择,只能将其删除:

    sed "s/GITHUB/${REPO}/g"
    

    kunwar.sangram 建议可以识别大写的I。)

    另一件事是您的某些变量可能包含您用于s 的分隔符,因此尝试使用另一个分隔符可能会解决它:

    sed "s|GITHUB|${REPO}|ig"
    

    【讨论】:

    • 第二个小费+1。听起来i / I不是的问题:OP 说它以交互方式工作,而 Ubuntu 上的库存 sed 是 GNU sediI工作。
    【解决方案3】:

    其中一个值包含斜线。您需要对其进行转义,或使用不同的分隔符。

    此外,您不必要地将多个调用串在一起,而单个调用会执行此操作。 cat 也没用。

    sed -e "s@PORT2@${PORT}@ig" \
        -e 's/IP2/IPADDRESS/ig' \ 
        -e 's/USER2/USER/ig' \
        -e 's/PASS2/PASSWORD/ig'  /crawler/bc_daemon.php > bc_daemon.php
    

    很遗憾,并非所有sed 方言都兼容。如果您不喜欢多个 -e 选项,请尝试使用单个以换行符分隔的 sed 命令字符串。我以这种语法提供第二个脚本作为示例。

    sed "s!GITHUB!${REPO}!ig
        s!COINNAME!${NAME}!ig"  /crawler/bc_layout.php > bc_layout.php
    

    如果您的值也可能包含@!,您将需要选择不同的分隔符。任何非字母数字的 ASCII 字符都可以,但反斜杠和引号显然是有问题的。

    【讨论】:

      【解决方案4】:

      cats 排除在外;他们更快乐地蜷缩在角落里,安静地离开。每个管道中的第一个sed 可以读取该文件。

      您也应该能够将这些单独的 sed 命令组合到每个管道中。也就是你当前的命令:

      cat /crawler/bc_daemon.php |
      sed "s/PORT2/${PORT}/ig" |
      sed 's/IP2/IPADDRESS/ig' |
      sed 's/USER2/USER/ig' |
      sed 's/PASS2/PASSWORD/ig' > bc_daemon.php
      

      应该是:

      sed -e "s/PORT2/${PORT}/ig" \
          -e 's/IP2/IPADDRESS/ig' \
          -e 's/USER2/USER/ig' \
          -e 's/PASS2/PASSWORD/ig' \
          /crawler/bc_daemon.php > bc_daemon.php
      

      这忽略了s/// 命令的未知选项的问题,可能可能指的是i 标志。 Linux 上的 GNU sed 手册页没有列出这一点,但在线 GNU sed 手册确实将 iI 列为不区分大小写的选项,所以这不应该是问题。另一种可能性是${PORT} 的扩展包含斜杠;这可能会导致您看到的错误(或者,问题出在第二个管道而不是第一个管道中)。

      如果您没有使用 GNU sed(并且错误提示您可能没有使用),您可能需要对模式进行暴力破解。

      sed -e "s/[pP][oO][rR][tT]2/${PORT}/g" \
          -e 's/[iI][pP]2/IPADDRESS/g' \
          -e 's/[uU][sS][eE][rR]2/USER/g' \
          -e 's/[pP][aA][sS][sS]2/PASSWORD/g' \
          /crawler/bc_daemon.php > bc_daemon.php
      

      请注意,如果当前目录是/crawler,这两个管道都会严重失败,因为输出重定向会在命令执行之前破坏输入文件。

      【讨论】:

      • 鉴于 OP 在 Ubunutu 上并声明命令在脚本之外工作,我想说i 可能不是问题。如果替换字符串确实包含斜杠,那么关于哪些字符最终会被误解为 s 选项的所有赌注都将失败。尝试sed 's/a/b/c/ig' <<<'a' 之类的方法 - 请注意错误消息如何命名有问题的选项。
      • 真正的问题似乎出在另一个管道中,并且是那里的替换字符串中的斜线(我提到这是一个可能的问题)。不区分大小写的东西并不是非常相关,但是 UUOC 和“一个sed 命令就足够了”和“当心当前目录是否为/crawler”都是有效的建议,即使不是非常赞成-值得。
      • 是的,您确实提到了斜线问题。我试图指出 unknown option to the s/// command, which is probably referring to the i flagnot using GNU 是红鲱鱼。
      • 感谢更新;您对包含有效建议的答案是正确的; +1。
      猜你喜欢
      • 2014-12-08
      • 2013-04-28
      • 2016-03-19
      • 1970-01-01
      • 2018-03-11
      • 2013-06-06
      • 2013-03-08
      • 2014-04-06
      • 2020-11-25
      相关资源
      最近更新 更多