从命令输出构建文件名会导致不明确的重定向错误

Building filename from command outputs results in ambigous redirect error

我想编辑一个文件并将其写入另一个位置,最后没有 .template。为此,我连续使用了两个命令,它们应该给我新的文件名,但 bash 不接受它。我听说你应该用反引号来做到这一点,但我无法让它工作(第一个 sed 是正确的,不要打扰):

sed -E '/^\s*(#.*)?$/d; s/^\s*(\S+)\s+("([^"]*)"|(\S+)).*/s\/\/\/g/' "$file" > `$(basename $file) | sed -E 's/(.*).template$/.translated/g')`

我收到这样的错误:

translate: command substitution: line 25: syntax error near unexpected token `)'
translate: command substitution: line 25: `$(basename $file) | sed -E 's/(.*).template$/.translated/g')'
translate: line 25: `$(basename $file) | sed -E 's/(.*).template$/.translated/g')`: ambiguous redirect

重定向到文件名部分应该是什么样的?

第 1 部分:为什么会发生

让我们看看为什么您会收到“不明确的重定向”错误。

当你运行:

foo > `$(basename $file) | sed -E 's/(.*).template$/.translated/g')`

...这是告诉 shell 首先 运行 一个命令:

$(basename $file) | sed -E 's/(.*).template$/.translated/g'

...并将其输出用作重定向目标。

但是,$(basename $file) | ...basename $file | ...一样!假设您的文件名为 /path/to/foo.template。在第一个命令替换发生后,它被翻译成:

foo.template | sed -E 's/(.*).template$/.translated/g'

...这是 运行宁 一个名为 foo.template 的命令并将其输出提供给 sed.

一个名为foo.template的命令吗?如果不这样做,那么只会在 stderr 上产生错误,而在 stdout 上什么也没有。由于 stdout 是输入 sed 的内容,这意味着 sed 根本没有接收到任何输入,所以它 写入 根本没有输出,所以你有一个空文件名。

并试图重定向到一个空文件名...是不明确的!这是你的错误。


第 2 部分:正确行事

我假设您的 sed 命令都执行您希望它们执行的操作(这意味着您 想要 foo.template 创建一个名为 .footranslated -- 如果你不想创建这个隐藏文件,你的第二个sed操作就大错特错了。

file_base=${file##*/}
sed -E '/^\s*(#.*)?$/d; s/^\s*(\S+)\s+("([^"]*)"|(\S+)).*/s\/\/\/g/' "$file" \
  >".translated${file_base%.template}"

...或者,如果您的实际意图是将扩展名 .template 替换为扩展名 .translated,则应该是:

file_base=${file##*/}
sed -E '/^\s*(#.*)?$/d; s/^\s*(\S+)\s+("([^"]*)"|(\S+)).*/s\/\/\/g/' "$file" \
  >"${file_base%.template}.translated"