grep 在终端命令行和 bash 脚本中有不同的结果

grep 在终端命令行和 bash 脚本中有不同的结果

我有一个 bash 脚本,它使用 grep 筛选出具有某些扩展名和某些目录下的文件。该脚本如下所示:

generate_exclud_extensions() {
  echo "\"(cpp$"
}

generate_exclude_dirs() {
  echo "|^test)\""
}

command=$(generate_exclud_extensions)$(generate_exclude_dir)
echo $command
git ls-files | grep -vE $command

该脚本应该筛选带有cpp扩展名的文件以及test目录下的文件。但结果只筛选掉了第一个,剩下了第二个。

事实 1:echo $command输出"(cpp$|^test)",并在终端中运行完整命令git ls-files | grep -vE ""(cpp$|^test)"",我得到了正确的结果。

事实 2:尝试使用 grep 两次,如下所示:

git ls-files | grep -vE "cpp$" | grep -vE "^test"

bash 脚本中出现同样的错误结果,但在终端中正确。

我一直在寻找,但还没有运气。如果有人能阐明这一点,我将不胜感激。

答案1

我设法重现了这个问题。这是两个函数中的 bash 转义问题。尝试这个:

generate_exclude_extensions() {
  echo '(cpp$'
}

generate_exclude_dirs() {
  echo '|^test)'
}

command=$(generate_exclude_extensions)$(generate_exclude_dirs)
echo "$command"
git ls-files | grep -vEe "$command"

我要重现的代码

generate_exclude_extensions() {
  echo '(cpp$'
}

generate_exclude_dirs() {
  echo '|^test)'
}

command=$(generate_exclude_extensions)$(generate_exclude_dirs)
echo "$command"
echo -e 'cpp\n
test\n
test456\n
display?5\n' | grep -vEe "$command"

您的脚本中还有两个错别字

generate_exclude_dir -> generate_exclude_dirs
generate_exclud_extensions -> generate_exclude_extensions

:) 玩得开心

答案2

另一种方法可能是:

generate_exclude_extensions() {
  echo 'cpp$'
}

generate_exclude_dirs() {
  echo '^test'
}

exclusions=$(
  generate_exclude_extensions
  generate_exclude_dir
)

printf '%s\n' "$exclusions"

git ls-files | grep -ve "$exclusions"

也就是说,每行有一个排除项,然后您甚至不需要-E.

答案3

你可以使用 Gitexclude 路径规范过滤输出:

exclude_extensions=( '*cpp' '*.txt' ) # added `*.txt` as sample file extension
exclude_dirs=( 'test/*' )             # exclude files in relative directory `test`

git ls-files "${exclude_extensions[@]/#/:(exclude)}" "${exclude_dirs[@]/#/:(exclude)}"

参数扩展扩展"${exclude_...[@]/#/:(exclude)}"为以空格分隔的数组条目,前缀为:(,路径规范“魔术词”exclude后跟)

结果命令相当于

git ls-files ':(exclude)*cpp' ':(exclude)*.txt' ':(exclude)test/*'

相关内容