在我的 .bash_aliases 中,我定义了一个从命令行使用的函数,如下所示:
search -n .cs -n .cshtml -n .html SomeTextIWantToSearchFor /c/code/website/ /c/stuff/something/whatever/
该函数构建一个 grep 命令,将结果通过管道传输到另一个 grep 命令(不幸的是,这很复杂,因为我陷入了旧版本):
search() {
local file_names opt OPTARG OPTIND pattern
file_names=()
while getopts ":n:" opt; do
case $opt in
n)
file_names+=( "$OPTARG" )
;;
esac
done
shift $((OPTIND-1))
pattern="$1"
shift
if (( ${#file_names[@]} > 0 )); then
file_names="${file_names[@]}"
file_names=${file_names// /':\|'}:
grep -I -r "$pattern" "$@" | grep "$file_names"
else
grep -I -r "$pattern" "$@"
fi
}
我定义了另一个函数来调用这个函数:
search-some-set-of-files() {
local file_names directories
file_names=( "-n page1.cshtml" "-n page2.cshtml" "-n page3.cshtml" )
directories=( "/c/code/website/" "/c/stuff/something/whatever/" )
search "${file_names[@]}" "$@" "${directories[@]}"
}
在命令行中,我这样调用该函数:
search-some-set-of-files SomeTextIWantToSearchFor
由于某种原因,结果包括每个文件在目标目录中。即,结果没有被 grep 根据我指定的文件名进行过滤。
如果我更改函数的最后一行search-some-set-of-files
以回显命令,我会得到以下结果:
$ search-some-set-of-files SomeTextIWantToSearchFor
search -n .cs -n .cshtml -n .html SomeTextIWantToSearchFor /c/code/website/ /c/stuff/something/whatever/
这正是我想要的。如果我将该命令复制(或逐字输入)到命令行中,结果就会如其应有。
如果我启用调试模式 ( set -x
),我可以看到 shell 单独引用每个参数:
$ search-some-set-of-files SomeTextIWantToSearchFor
+ search-some-set-of-files SomeTextIWantToSearchFor
+ local file_names directories
+ file_names=("-n page1.cshtml" "-n page2.cshtml" "-n page3.cshtml")
+ directories=("/c/code/website/" "/c/stuff/something/whatever/")
+ search '-n page1.cshtml' '-n page2.cshtml' '-n page3.cshtml' SomeTextIWantToSearchFor /c/code/website/ /c/stuff/something/whatever/
+ return
+ etc...
所以我认为问题在于如何将参数传递给函数search
。我该如何解决?
答案1
你的问题是第二个grep
:
... | grep "$file_names"
-n
当您调用函数时,和文件名 ( )之间的空格-n page1.cshtml
包含在$file_names
数组中。然后,替换:
file_names=${file_names// /':\|'}:
:\|
由于前导空格,将在字符串的开头添加一个额外的内容。所以,你的第二个grep
命令实际上是:
... | grep ":\|page1.cshtml:\|page2.cshtml:\|page3.cshtml:"
结果,grep
匹配全部行,因为所有结果行都将包含filename:
和 匹配的行:
。
因此,一个简单的解决方案是删除空格:
file_names=( "-npage1.cshtml" "-npage2.cshtml" "-npage3.cshtml" )
然后一切都应该按预期进行。