Bash/sed:没有那个文件或目录

Sho*_*ine 1 bash sed

我有一个名为 script.sh 的脚本:

FILE=$1
sed -i.bak "s|needle|pin|g" $FILE
Run Code Online (Sandbox Code Playgroud)

如果我像这样运行它:

bash ./script.sh /var/www/path/to/file
Run Code Online (Sandbox Code Playgroud)

我得到这个回应:

: No such file or directoryth/to/file
Run Code Online (Sandbox Code Playgroud)

如果我自己运行sed,则通过相同的路径:

sed -i.bak "s|needle|pin|g" "/var/www/path/to/file"
Run Code Online (Sandbox Code Playgroud)

它工作正常(甚至正确替换值)。

我究竟做错了什么?

额外的观察:我假设它告诉我入口路径是错误的,但很难说,因为它说“:没有这样的文件或目录/到/文件”,这向我表明其他东西是错误的。也许与回车有关?

ran*_*mir 6

您应该在变量周围使用引号以防止分文件名扩展

file="$1"
sed -i.bak "s|needle|pin|g" "$file"
Run Code Online (Sandbox Code Playgroud)

(您也不应该对非环境变量使用全大写的变量名。)


在 中bash,每个命令行(在它被分成标记之后)经历一系列的shell 扩展,以特定的顺序(强调我的):

  • 大括号扩展;
  • 波浪号扩展、参数和变量扩展、算术扩展、进程替换和命令替换(以从左到右的方式完成);
  • 分词;和
  • 文件名扩展

所以,当你写:

file='filename with spaces'
sed "pat" $file
Run Code Online (Sandbox Code Playgroud)

$file令牌将进行变量扩展,其次是分词,命令会是这个样子:

sed pat filename with spaces
Run Code Online (Sandbox Code Playgroud)

意思是,sed收到三个词作为文件名,而不是一个。

如果使用双引号,则双引号内发生的参数扩展、命令替换和算术扩展的结果不受分词文件名扩展的影响。在我们的例子中:

file='filename with spaces'
sed "pat" "$file"
Run Code Online (Sandbox Code Playgroud)

扩展为:

sed "pat" "filename with spaces"
Run Code Online (Sandbox Code Playgroud)

保留文件名中的空格。