sed未知选项为's';在bash脚本中

sed未知选项为's';在bash脚本中,bash,sed,Bash,Sed,我在编写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/

我在编写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'
当它可以照字面理解时,我使用“”;当它需要打印变量时,我使用“”

在我看来,这应该是可行的。但是我不知道我的错误在哪里

试试看

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

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

sed "s/GITHUB/${REPO}/g"
(建议改为识别大写的
I
。)

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

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

其中一个值包含斜杠。您需要转义它,或者使用不同的分隔符

此外,您不必要地将多个调用串在一起,而一个调用就可以了。
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字符都可以,但反斜杠和引号显然有问题。

不要使用
cat
s;他们更高兴蜷缩在角落里,安静地离开。每个管道中的第一个
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
手册页没有列出这一点,但在线手册确实列出了
i
i
作为不区分大小写的选项,所以这应该不是问题所在。另一种可能性是,
${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
,则这两个管道都将严重失败,因为输出重定向将在执行命令之前对输入文件进行重击。

我将假设
REPO
中有斜杠,这将过早终止
s/
命令。尝试使用不同的分隔符
s
s@
REPO
value.FYI中不包含的内容。BashFAQ 21建议了一些替换方法,这些方法没有
sed
要求内容中不存在分隔符的限制。看@Etan Reisner,就是这样。非常感谢你。我没想到回购协议是一个url,所以里面有/。谢谢大家的帮助:)+1第二条提示。听起来好像
i
/
i
不是问题:OP说它是交互工作的,Ubuntu上的stock
sed
是GNU
sed
,其中
i
i
都起作用。假设OP在Ubunutu上,并且声明命令在脚本之外工作,我想说,
I
可能不是问题所在。如果替换字符串确实包含斜杠,那么所有关于哪些字符最终会被误解为
s
选项的赌注都将取消。尝试类似于sed's/a/b/c/ig的方法。真正的问题似乎是在另一个管道中,并且是替换字符串中的斜杠(我提到了这是一个可能的问题)。不区分大小写的东西没有太大关系,但UOOC和“一个
sed
命令就足够了”和“当心当前目录是否为
/crawler
”都是有效的建议,即使不是非常值得投票。是的,你提到了斜杠问题。我想指出的是,s///命令的
未知选项可能是指I标志
不使用GNU
都是骗人的;关于你的答案中包含有效建议,你是对的+1.