我写了一个过滤器/选择函数,它接受一个函数和一个流作为输入。它应该产生一个新的 ( 2 4 ) 数组。然而,我的结果是什么。我怀疑它与IFS有关。
# func int -> bool
is_even () { (( $1 % 2 == 0 )) ;}
# func func -> int
filter () {
local function_to_apply=$1
local arg
while read -r arg; do
$function_to_apply $arg && echo $arg
done;:
}
# int array
integers=( 1 2 3 4 )
result=$(echo "${integers[*]}" | filter is_even)
declare -p result
Run Code Online (Sandbox Code Playgroud)
输出是一个字符串 ""
declare -- result=""
Run Code Online (Sandbox Code Playgroud)
预期输出是一个数组 ( 2 4 )
declare -a result ='([0]="2" [1]="4")'
Run Code Online (Sandbox Code Playgroud)
在信用到期时给予信用:
http://www.binaryphile.com/bash/2018/07/26/approach-bash-like-a-developer-part-1-intro.html
您可以在一行中输入您的函数。该行将是字符串1 2 3 4,它"${integers[*]}"以默认值$IFS. 整个单行将在第一次调用readinto 时读取,arg并在调用您的函数时使用(未加引号)。由于$arg未加引号,shell 会将字符串吐在空格上,而您的函数将仅使用该初始值1,这不是偶数。这意味着echo $arg未触发。
反而:
#!/bin/bash
is_even () { (( $1 % 2 == 0 )) ;}
filter () {
local function_to_apply="$1"
local arg
while read -r arg; do
"$function_to_apply" "$arg" && echo "$arg"
done
}
integers=( 1 2 3 4 )
result=$(printf '%s\n' "${integers[@]}" | filter is_even)
declare -p result
Run Code Online (Sandbox Code Playgroud)
这里的主要内容是在filter函数的各个行上打印数组的元素。
这将为您提供单个字符串2\n4(\n换行符在哪里)。这应该不足为奇,因为您将字符串分配给result.
如果你想取回一个数组,你可以在最近的版本中做到这一点bash:
#!/bin/bash
is_even () { (( $1 % 2 == 0 )) ;}
filter () {
local func="$1"
local -n in_array="$2"
local -n out_array="$3"
local element
out_array=()
for element in "${in_array[@]}"; do
if "$func" "$element"; then
out_array+=( "$element" )
fi
done
}
integers=( 1 2 3 4 )
even_ints=()
filter is_even integers even_ints
declare -p even_ints
Run Code Online (Sandbox Code Playgroud)
这是在filter函数内部使用两个名称引用变量。第一个是输入数组,第二个是输出数组。
这会给你输出
declare -a even_ints=([0]="2" [1]="4")
Run Code Online (Sandbox Code Playgroud)
将值传递给filter函数的另一种方法显然是在函数的命令行上传递它们:
declare -a even_ints=([0]="2" [1]="4")
Run Code Online (Sandbox Code Playgroud)