【问题标题】:Why won't this bash function work the same as when running directly?为什么这个 bash 函数的工作方式与直接运行时不同?
【发布时间】:2016-02-20 00:45:53
【问题描述】:

我在/etc/bashrc中写了一个函数,因为我经常使用它,但现在它似乎不起作用:

function replaceall() {
  find "$1" -type f -exec sed -i "s|$2|$3|g" {} \;
}

当直接运行它时,我会做类似的事情:

find ./*/conf/production/*.conf -type f -exec sed -i "s|/home/user/sites|/var/www/vhosts|g" {} \;

效果很好。但是当使用replaceall 函数调用时它不起作用:

replaceall ./*/conf/production/*.conf "/home/user/sites" "/var/www/vhosts"

注意:当我使用 replaceall . [...] 时它确实有效,这让我想知道,我是否遗漏了一些关键语法?

【问题讨论】:

  • 您在 "$1" 周围缺少一些双引号,首先。
  • 谢谢@TomFenech,我已经完成了并更新了我的问题。
  • 注意./*/conf/production/*.conf 会被扩展,所以$2 可能包含这些扩展之一。通过说echo find ... 进行调试,看看到底有什么。
  • 啊哈! @fedorqui 是的,它只回显了一行,$1$2$3 分别是找到的前三个文件。我用引号调用它(replaceall "./*/..." ... 但这只是说找不到文件。有没有办法实现两者?
  • 你确定你肯定需要使用find吗?如果是这样,您可能应该使用-name '*.conf',结合-prune 跳过不包含conf/production 的路径(尽管我不确定我脑海中的确切语法......)

标签: bash sed find


【解决方案1】:

看起来你根本不依赖 find 的遍历能力,所以我建议你只使用带循环的 glob 扩展:

replaceall() {
    for file in $1; do
        sed -i.bak "s|$2|$3|g" "$file"
    done
}

然后调用脚本,引用每个参数:

replaceall "./*/conf/production/*.conf" "/home/user/sites" "/var/www/vhosts"

引用每个参数可确保路径的扩展发生在函数内。我还为-i 开关添加了一个后缀,以便对每个受影响的文件进行备份,否则您的脚本非常危险!

正如 cmets 中所述,这种方法仍然存在潜在问题。如果您想传递包含空格的路径,则必须将其转义以防止分词。例如,"./*/conf/production files/*.conf" 之类的路径需要在空格 "./*/conf/production\ files/*.conf" 前面加上反斜杠。

【讨论】:

  • 一个警告:分词发生在路径名扩展之前,所以这不适用于像"./*/conf/production files/*.conf" 这样的第一个参数。您必须转义任何空格:".../production\ files/*.conf".
  • @chepner 谢谢,我更新了我的答案以提及这一点。
  • 感谢@TomFenech,这似乎是最明智的做法,至少在我需要that find 可以提供的额外功能之前。 P.S 对不起,上面写错了你的名字! ;)
  • @Leonard 不用担心 - 我还是删除了编辑摘要,因为它与未来的读者无关。顺便说一句,这远不是我名字中最糟糕的拼写!
【解决方案2】:

我会这样写:

function replaceall() {
  local search=$1
  local replace=$2
  shift 2
  for i in "$@"
      find "$i" -type f -exec sed -i "s|$search|$replace|g" {} \;
  done
}

replaceall "/home/user/sites" "/var/www/vhosts" ./*/conf/production/*.conf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-04
    • 2011-06-19
    • 2022-01-26
    • 2017-08-26
    • 2017-09-27
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多