为什么这个 Shell 脚本不起作用?

为什么这个 Shell 脚本不起作用?

我有以下 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

所以它不是一组带有值的键,而是两个位置参数。

相关内容