Bash

使用參數列表呼叫另一個函式的函式不起作用

  • November 10, 2014

在我的 .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函式。我該如何解決?

你的問題是第二個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" )

然後一切都應該按預期工作。

引用自:https://unix.stackexchange.com/questions/167172