bash - 传递变量来查找命令-exec

标签 bash sed

我有一个像这样的脚本:

#!/usr/bin/env bash

OLD_PATH_BASE=./components/
NEW_PATH_BASE=../../../react_components/

find . -regextype sed -regex "\./rockstart_\w\+_app/static/js/\w\+\.js" -exec sed -i "s@^\(import \w\+ from '\)$OLD_PATH_BASE\(\w\+/\w\+\.jsx';\)@\1$NEW_PATH_BASE\2@" {} \;

这正如我所期望的那样,但是当我这样做时:

#!/usr/bin/env bash

OLD_PATH_BASE=./components/
NEW_PATH_BASE=../../../react_components/

SED_COMMAND='sed -i "s@^\(import \w\+ from '"'\)$OLD_PATH_BASE\(\w\+/\w\+\.jsx';\)@\1$NEW_PATH_BASE\2@"'"'
find . -regextype sed -regex "\./rockstart_\w\+_app/static/js/\w\+\.js" -exec $SED_COMMAND {} \;

它不起作用并给我错误:

sed: -e expression #1, char 1: unknown command: `"'

即使当我回显$SED_COMMAND时,它也会显示正确的命令。怎么了

最佳答案

数组可以工作:

#!/usr/bin/env bash

old_path_base=./components/
new_path_base=../../../react_components/

# this is totally unnecessary, but IMHO makes your code easier to read
# ...huge long lines being unweildy by nature, after all.
sed_pieces=(
   's'
   "^\(import \w\+ from '\)${old_path_base}\(\w\+/\w\+\.jsx';\)"
   "\1${new_path_base}\2"
   '' # flags; empty set
)

# ...using an array for sed_command is the important part:
IFS='@' # this makes "${array[*]}" combine pieces with @s
sed_command=( sed -i "${sed_pieces[*]}" )

find . -regextype sed \
  -regex "\./rockstart_\w\+_app/static/js/\w\+\.js" \
  -exec "${sed_command[@]}" {} +

说明:

  • 扩展不带引号的字符串(如失败的尝试)不会通过完整的解析器运行扩展结果,而是仅通过字符串分割和全局扩展阶段;因此,引号不会被解析和消耗。这是一个功能,而不是一个错误——如果每个扩展都运行完整的解析器,那么在 shell 中编写安全代码实际上是不可能的。阅读 BashFAQ #50有关当前行为和最佳实践解决方法的完整说明。

    提供一个更短、更简单的示例:

    a_command='touch "hello world"'
    $a_command
    

    ...实际上会创建两个文件:一个名为“hello,另一个名为world”;这是因为 $a_command 运行的唯一处理步骤是字符串分割(根据空格分割成单词)和 glob 扩展(评估该分割过程创建的每个项目以查看它是否是 glob 表达式,并将其替换为匹配文件列表(如果是)。

  • -exec ... {} + 将多个输入文件名传递给 exec 命令的每次调用;因此,在允许的情况下,这是一种效率改进(这里肯定是这种情况,因为任何支持 -i 扩展的 sed 也将支持多个输入文件)。

关于bash - 传递变量来查找命令-exec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38024121/

相关文章:

linux - 使用 LINUX top 命令计算已用内存百分比

bash - 当我登录 GUI 时,波浪号扩展不起作用

bash - 如何使用 bash 脚本递归地从文件中删除特定扩展名

awk - 使用 sed 删除特定列的小数

regex - 流水线 sed 调用和多个 sed 表达式之间的效率是否存在差异?

linux - 无需 cron 即可递归执行脚本

bash - mysql_secure_installation 的答案

regex - 使用 sed 或其他 bash 工具删除字符串末尾的模式

linux - 如何将 .CSV 文件的标题与动态字段名称相匹配

regex - sed 是否匹配第一个字符?