我有以下 shell 脚本
#!/bin/bash
# Search elixir code with ack
# By default skip the dependencies and test directories
ignore_dirs=("dependencies" "test" "config")
# the for call below inserts newlines so we need to strip them out which is why the tr -d part is on the end
# of the assignment
ign_dirs="$(for i in "${ignore_dirs[@]}"; do echo "--ignore-dir=$i "; done | tr -d '\n')"
# By default skip the mix.exs file
ignore_files=("is:mix.exs" "is:credo.exs")
ign_files="$(for i in "${ignore_files[@]}"; do echo "--ignore-file=$i "; done | tr -d '\n')"
pager=less
file_types=elixir:ext:ex,exs,eex,heex
#echo ack $1 --word-regexp --pager="$pager" --type-set="$file_types" "$ign_dirs" "$ign_files" --noenv
# Array variation
ack $1 --word-regexp --pager="$pager" --type-set="$file_types" "$ign_dirs" "$ign_files" --noenv
# Hardcoded variation
ack $1 --word-regexp --pager=less --type-set=elixir:ext:ex,exs,eex,heex --ignore-dir=dependencies --ignore-dir=test --ignore-dir=config --ignore-file=is:mix.exs --ignore-file=is:credo.exs --noenv
我使用注释掉的回声线创建了硬编码变体。当我运行硬编码变体时,ack按预期工作。当我运行数组变体时,好像 ack 没有看到命令行选项——例如,包含 mix.exs,尽管它不应该包含在内,并且它会搜索测试目录。
是我的shell脚本错误吗?我复制/粘贴了大部分 shell 脚本——我的意思是我可以echo $ign_dirs
并且看到了正确的值,当我运行命令(数组变体)时,它无法正常工作,这似乎表明我的 shell 脚本没有问题。
顺便说一句,我在 Mac 上的 zsh 上运行这个。我在 bash 下测试了这个,我看到了同样的问题。
如果这是某处的某种确认常见问题解答,请提前致歉。我确实检查过,但没有找到任何可以解决问题的内容。
编辑:
我可以看出我并没有说得那么清楚。
最终我试图用 ack 自动搜索 Elixir 代码。我希望尽可能将选项/搜索保留在 bash 脚本中,这样我就不必担心不同计算机上 .ackrc 文件和环境变量的变化。
我期望的是,当 ack 搜索文件时,它将排除我在ignore_dirs中列出的目录,并跳过我在ignore_files中指定的文件。当我使用硬编码变体运行 shell 脚本时,目录会被忽略。当我使用数组变体运行 shell 脚本时,它们不会被忽略。
是的,我知道 ign_dirs 和 ign_files 是字符串而不是数组。是否可以在shell脚本的命令行中直接使用数组?
答案1
为选项构建数组--ignore-*
:
ignore_dirs=("dependencies" "test" "config")
ign_dirs=()
for i in "${ignore_dirs[@]}"; do
ign_dirs+=("--ignore-dir=$i");
done
ignore_files=("is:mix.exs" "is:credo.exs")
ign_files=()
for i in "${ignore_files[@]}"; do
ign_files+=("--ignore-file=$i");
done
然后在命令中使用这些数组:
ack "$1" --word-regexp --pager="$pager" --type-set="$file_types" "${ign_dirs[@]}" "${ign_files[@]}" --noenv
答案2
在最终命令中删除变量周围的引号。
ack $1 --word-regexp --pager="$pager" --type-set="$file_types" $ign_dirs $ign_files --noenv
这些变量中有多个以空格分隔的部分,并且您希望它们以空格分隔。
原始代码(带引号)扩展为:
ack $1 --word-regexp --pager=less --type-set=elixir:ext:ex,exs,eex,heex "--ignore-dir=dependencies --ignore-dir=test --ignore-dir=config" "--ignore-file=is:mix.exs --ignore-file=is:credo.exs" --noenv
所以它不是一组带有值的键,而是两个位置参数。