我正在尝试设置一个脚本,该脚本将从 github 获取更改,其中脚本具有在 Mac OS X 中无法执行的命令。
我的目标是使用sed
etc 来替换该脚本中的命令。
这些是命令:
原始命令(在脚本中替换):
DIR=$(dirname "$(readlink -f $0)")
新命令(我想替换为):
DIR="$(cd "$(dirname "$0")" && pwd -P)"
到目前为止我尝试过的:
StartStopScript="/path/to/script.sh"
DIRnew=""$(cd "$(dirname "$0")" && pwd -P)""
DIRold=""$(dirname "$(readlink -f $0)")""
echo "$StartStopScript" | sed -e 's/"$DIRold"/"$DIRnew"/g'
这失败了,命令似乎被执行而不是解释为字符串。
图它归结为引用sed
。
感谢我能得到的任何帮助。
答案1
OrigScript="/path/to/script.sh"
echo $OrigScript
/path/to/script.sh
#note: no quotes
OrigScript='"/path/to/script.sh"'
echo $OrigScript
"/path/to/script.sh"
#note: with quotes, but not good for filesnames, rather use "$filename" in the command argument
DIRnew='"$(cd "$(dirname "$0")" \&\& pwd -P)"'
echo $DIRnew
"$(cd "$(dirname "$0")" \&\& pwd -P)"
#note: with quotes, escaping & needed for suppressing interpretation by sed
DIRold='"$(dirname "$(readlink -f $0)")"'
echo $DIRold
"$(dirname "$(readlink -f $0)")"
#note: in your question the original DIR=.. did NOT have double quotes,
#I assume a typo
sed -e "s/$DIRold/$DIRnew/g" "$OrigScript"
#note: $OrigScript should NOT have the double quotes in it!
#note: I assume $OrigScript == $StartStopScript
#test:
echo $DIRold | sed "s/$DIRold/$DIRnew/"
"$(cd "$(dirname "$0")" && pwd -P)"
#result includes double quotes!
1)要使用(双)引号声明变量,您需要对引号进行转义以使引号包含在字符串中,最好使用单引号以确保内部的字符串完全是字符串并且不会解释任何变量。这也简化了&
, 和的使用,$()
因为 shell 不会解释它们
2) 对于echo
ing(双)引号,转义它们
3) 为了允许sed
解释 shell 变量,您必须在sed
命令周围使用双引号(使用单引号时,命令sed 's/$a/$b/'
将尝试将实际字符串 '$a' 替换为字符串 '$b' ,还要注意特殊情况$
in )的含义sed
,命令中的变量周围sed
不需要双引号,就像sed
处理具有任何字符的字符串一样(对 的特殊命令字符有限制sed
)。
4)echo "$StartStopScript" | sed -e 's/"$DIRold"/"$DIRnew"/g'
将回显变量$StartStopScript
(我假设这只是脚本的文件名)并尝试替换该字符串中的变量(即文件名)。对于应用于sed
文件,请使用sed 's/a/b/g' file
(输出写入stout
),对于覆盖文件,请使用-i
(小心使用,即首先测试正确的替换)
5)&
在 中具有特殊含义sed
,它重新打印初始(匹配)模式:
echo ABC | sed 's/A/&12/'
A12BC
您必须在替换模式中转义它以抑制解释:
echo ABC | sed 's/A/\&12/'
&12BC
因此,变量的$DIRnew
字符串中需要有转义反斜杠。
6)除此之外,我建议使用循环来if
识别操作系统并相应地调整命令。这样,您只需要一个脚本即可用于两种操作系统。 IE
if [ OS = Mac ] ; then
dir=MacDir
else
dir=LinuxDir
fi