使用参数列表调用另一个函数的函数不起作用

Big*_*uge 6 bash shell-script function arguments

在我的 .bash_aliases 中,我定义了一个从命令行使用的函数,如下所示:

search -n .cs -n .cshtml -n .html SomeTextIWantToSearchFor /c/code/website/ /c/stuff/something/whatever/
Run Code Online (Sandbox Code Playgroud)

该函数构建了一个 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
}
Run Code Online (Sandbox Code Playgroud)

我定义了另一个调用这个函数的函数:

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[@]}"
}
Run Code Online (Sandbox Code Playgroud)

在命令行中,我像这样调用这个函数:

search-some-set-of-files SomeTextIWantToSearchFor
Run Code Online (Sandbox Code Playgroud)

出于某种原因,结果包括目标目录中的每个文件。即,结果没有根据我指定的文件名被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/
Run Code Online (Sandbox Code Playgroud)

这正是我想要的。如果我将该命令(或逐字输入)复制到命令行中,则结果应该是这样。

如果我启用调试模式 ( 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...
Run Code Online (Sandbox Code Playgroud)

所以我认为问题在于如何将参数传递给search函数。我该如何解决?

ter*_*don 6

你的问题是第二个grep

... | grep "$file_names"
Run Code Online (Sandbox Code Playgroud)

当您调用您的函数时,-n和文件名 ( -n page1.cshtml)之间的空格包含在$file_names数组中。然后,替换:

file_names=${file_names// /':\|'}:
Run Code Online (Sandbox Code Playgroud)

:\|由于前导空格,将在字符串的开头添加一个额外的。所以,你的第二个grep命令实际上是:

... | grep ":\|page1.cshtml:\|page2.cshtml:\|page3.cshtml:"
Run Code Online (Sandbox Code Playgroud)

因此,grep匹配所有行,因为所有结果行都将包含filename:并且由:.

因此,一个简单的解决方案是删除空格:

file_names=( "-npage1.cshtml" "-npage2.cshtml" "-npage3.cshtml" )
Run Code Online (Sandbox Code Playgroud)

然后一切都应该按预期工作。