我有一个名为script.sh的脚本:
FILE=$1
sed -i.bak "s|needle|pin|g" $FILE
如果我这样运行:
bash ./script.sh /var/www/path/to/file
我收到了这个回复:
: No such file or directoryth/to/file
如果我自己运行sed
,则传递相同的路径:
sed -i.bak "s|needle|pin|g" "/var/www/path/to/file"
它工作正常(甚至正确地替换了值)。
我做错了什么?
奖金观察:我假设它告诉我输入路径错误但很难说,因为它说“:没有这样的文件或目录/ /文件”,这对我来说别的东西是错的。也许马车回归有关?
答案 0 :(得分:2)
您应该在变量周围使用引号来阻止word splitting和filename expansion:
file="$1"
sed -i.bak "s|needle|pin|g" "$file"
(对于非环境变量,您还应该not use all-caps variable names。)
在bash
中,每个命令行(在它被分成标记之后)经历了一系列shell expansions,按特定顺序(强调我的):
- 支撑扩张;
- 代码扩展,参数和变量扩展,算术扩展,进程替换和命令替换(以从左到右的方式完成);
- 分词;和
- 文件名扩展。
所以,当你写:
file='filename with spaces'
sed "pat" $file
$file
令牌将经历变量扩展,然后是分词,现在该命令将如下所示:
sed pat filename with spaces
意思是,sed
收到了三个用于文件名的单词,而不是一个单词。
如果使用双引号,则在双引号内发生的参数扩展,命令替换和算术扩展的结果不会受分词和< em>文件名扩展。在我们的例子中:
file='filename with spaces'
sed "pat" "$file"
扩展为:
sed "pat" "filename with spaces"
保留文件名中的空格。
答案 1 :(得分:1)
路径字符串变量中必须有一些不可打印的控制字符,您可以使用declare -p
打印它的内容:
FILE=$1
declare -p FILE