Bash

循環輸入並在bash中執行命令的通用函式?

  • June 26, 2019

我試圖創建一個循環輸入並執行命令的函式——不管它們是如何分隔的。

function loop {
   # Args
   #     1: Command
   #     2: Inputs
   for input in "$2" ; do                     
       $1 $input
   done
}
declare -a arr=("1" "2" "3")

$ loop echo "$arr[@]"
1

$ loop echo 1 2 3
1

$ loop echo $arr
1

但是根據這個答案,for .. in ..適用於數組:

for item in "${arr[@]}" ; do
  echo "$item"
done

它也適用於空格分隔的值:

for item in 1 2 3 ; do
  echo "$item"
done

簡而言之,我如何在傳遞參數時獲得"${arr[@]}"效果1 2 3

是否可以將這種循環概念擴展到任何類型的分隔項,例如\n文件等分隔內容?在 Python 中我們有一個概念iterators,在 bash 中是否有類似的東西?

您沒有正確呼叫數組。 $arr只會擴展至數組中的第一個元素,並將擴展至第一個元素並附加$arr[@]文字字元串。[@]

要呼叫數組的所有元素,請使用:"${arr[@]}"

您遇到的另一個問題是$2僅包含第二個位置參數,您嘗試在其中迭代第 3、第 4、第 5 等。它們都將儲存在$@.

為了實現您的目標,您可以執行以下操作:

function loop {
   local command=$1
   shift
   for i in "$@"; do
       "$command" "$i"
   done
}

這將設置command為第一個位置參數,然後移位,以便$@可以用來循環剩餘的參數。然後你只需要正確呼叫數組:

$ declare -a arr=("element1" "element2" "element3")
$ loop echo "${arr[@]}"
element1
element2
element3
$ loop printf 'hello ' 'world\n'
hello world
$ loop touch file1 file2 file3
$ ls
file1  file2  file3

如果您希望此函式能夠接受各種分隔符,您可以執行以下操作:

function loop {
   local command=$1
   local delim=$2
   shift 2
   set -- $(tr "$delim" ' ' <<<"$@")
   for i in "$@"; do
       "$command" "$i"
   done
}

這意味著您必須通過第二個參數指定正在使用的分隔符,例如:

$ loop echo '|' 'one|two|three'
one
two
three
$ loop echo '\n' "$(printf '%s\n' 'one' 'two' 'three')"
one
two
three

但是,這有一些錯誤(如果您指定自定義分隔符,它仍將由空格分隔)

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