【问题标题】:How to create array-variable from function argument input -- Remove Array Blanks function如何从函数参数输入创建数组变量——删除数组空白函数
【发布时间】:2021-10-08 04:13:53
【问题描述】:

seeing this question 之后,我决定组合一个函数来删除数组中的空元素,以防它为某人节省几秒钟的时间。

有没有办法将动态命名的输入数组变量作为函数的输出返回(或导出)?

理想情况下

  1. 用户来电:removeArrayBlanks "newArrayName" "arrayItem1" "" "arrayItem2"...
  2. 该函数取消设置旧数组并创建:${newArrayName[@]},它扩展为 "arrayItem1" "arrayItem2",没有任何空白项或非顺序索引号

另外,是否有人对该功能有任何优化/建议?我已经包含了下面的功能。谢谢!

removeArrayBlanks() {
    # Usage: Provide array as input, store output as array. 
    # Example 1: mapfile -t lastArray < <(removeArrayBlanks "hate" "" "empty" "array" "items")
    # Example 2: mapfile -t lastArray < <(removeArrayBlanks "${inputArray[@]}")
    [[ $# -lt 2 ]] && echo "Usage: Provide array as an argument." && exit 1 # Ensure input is array
    tempArray=( "$@" ) # Rebuild array from inputs
    for i in "${!tempArray[@]}"; do
        [[ ! -z "${tempArray[$i]}" ]] && finalArray+=( "${tempArray[$i]}" ) # Add non-empty strings
    done && printf '%s\n' "${finalArray[@]}" && unset tempArray && unset finalArray
}

【问题讨论】:

  • 除非你声明它是本地的,否则函数中分配的变量在主脚本中是可见的,所以你不需要返回它。
  • 您想从原始数组中删除“空白”,还是创建一个没有“空白”的全新数组?
  • ! -z 看起来很奇怪。
  • @Barmar ty,很难从用户输入中获取名为 $1 的新数组。我找不到一种简单的方法来“更新”输入数组,而无需强制用户必须调用新的数组名称。
  • @markp-fus 试图从输入数组中删除空白。而且,理想情况下,不必重命名它或声明一个新数组。

标签: arrays bash shell reference


【解决方案1】:

假设:

  • 目标是从当前数组中删除包含空字符串(又名'blanks')的数组元素
  • 函数应该能够适用于传递给函数的任何数组(名称)
  • OP 正在运行,或者可以升级到/以上,bash 4.3+(需要nameref 支持)

注意:仅“删除”数组元素 unset 数组引用(例如,unset array[index#1]

在函数中使用nameref和unset命令的一个想法:

function removeArrayBlanks() {

declare -n localarray="${1}"                                  # define nameref; remains a local array variable

for i in "${!localarray[@]}"                                  # loop through indices
do
    [[ -z "${localarray[${i}]}" ]] && unset localarray[${i}]  # remove entries that contain empty strings
done
}

运行中:

$ myarray=( a "" 1 "" A )
$ typeset -p myarray
declare -a myarray=([0]="a" [1]="" [2]="1" [3]="" [4]="A")

$ removeArrayBlanks myarray
$ typeset -p myarray
declare -a myarray=([0]="a" [2]="1" [4]="A")

# verify localarray not known by parent
$ typeset -p localarray
-bash: typeset: localarray: not found

【讨论】:

  • 谢谢@markp-fuso!我没有意识到变量会在调用函数的当前上下文/shell中更新。我想我不得不以某种方式“导出”新数组。
  • 啊,我明白了……我想我没看错吧?我只是没有意识到这是可能的:declare -n“为每个名称赋予 nameref 属性,使其成为对另一个变量的名称引用。另一个变量由 name 的值定义。所有引用、赋值和属性修改命名,除了那些使用或更改 -n 属性本身的,都是在由 name 的值引用的变量上执行的。”
  • 请记住,函数调用(本质上)是宏调用(想想replace '&lt;function-name&gt;' with '&lt;function_body&gt;')而不是子进程调用;最终结果是您在函数中所做的任何事情都实际应用于“父”进程;一个例外是,如果您将变量定义为函数的“本地”,在这种情况下,“父级”看不到它;在这种情况下,“nameref”是一个“本地”变量,它还兼作传入数组名称的引用(而不是副本)
  • 我选择先填充数组,然后删除/取消设置空字符串;你仍然可以实现你的逻辑......在将值分配给数组之前过滤掉空字符串......通过一个函数,但也使用nameref来消除创建/打印/垃圾'临时'数组的开销...... . 你的选择
  • 是的,添加 nameref 是我没有意识到的一件事。我看到的另一件事是没有将数组扩展为函数参数。也就是说,我正在做removeArrayBlanks ${inputArray[@]},我收集到这会导致数组名称丢失,因为数组在函数可以对其执行操作之前被扩展。
猜你喜欢
  • 2014-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 1970-01-01
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多