以变量作为输入和输出从键值对中获取值

问题描述 投票:0回答:4

我在脚本中有一组部门名称和部门代码。 用户将选择一个部门名称,然后将其分配给一个变量;我需要

  • 读取数组(deptCodeArray)
  • 找到用户选择的部门名称(departmentName)
  • 从数组中获取与部门名称匹配的部门代码,并将其设置为稍后将使用的变量(deptCode)。 此脚本使用 MDM 工具 (Jamf) 在远程 macOS 计算机(macOS Big Sur 或更高版本)上运行。
# This is an array of Department Namse and matching Department Codes embedded 
# in the script. I have full control over this array.

deptCodeArray="
Information Technology=IT,
Marketing=MA,
Finance=FI
"

# The Department Name will be selected by the user when the script runs 
# (The full script includes a user dialog with a menu of department 3 names 
# to select from.)

departmentName="Information Technology"

# The Department Code is the desired output, to be used later in the script.
# In this case it should be deptCode=IT

deptCode=""


我已经尝试了几种不同的方法来让它工作。 显然 macOS 不支持关联数组? 我从“declare -A deptCodeArray”开始,但显然这需要 bash 4,macOS 不附带,安装不是一个选项。

我正在尝试 awk,但我在理解如何使它起作用时遇到了一些麻烦,而且我不确定其他方法是否可行。 我也不确定我是否有正确的数组语法。

bash macos key-value
4个回答
1
投票

deptCodeArray
不是 bash 数组,它是一个标量变量,它的值是一个文本字符串。让我们首先使用
tmp
特殊变量将其转换为真正的 bash 索引数组(
IFS
),并在删除尾随逗号后使用键值对填充 bash 关联数组(
arr
):

$ declare -a tmp=() # indexed array
$ declare -A arr=() # associative array
$ set -f; IFS=$'\n' tmp=( $deptCodeArray ); set +f # populate tmp
$ for s in "${tmp[@]%,}"; do arr["${s%%=*}"]="${s#*=}"; done # populate arr

然后,找到键

"Information Technology"
的值:

$ departmentName="Information Technology"
$ deptCode="${arr[$departmentName]}"
$ echo "$deptCode"
IT

备注:

  • IFS
    是一个 bash 特殊变量,用于分隔表达式中的字段。
    IFS=$'\n'
    将其设置为换行符。在与数组赋值 (
    IFS=$'\n' var=value
    ) 相同的命令中设置它会将效果限制为赋值。丢弃前导和尾随换行符。分配后,每个
    tmp
    条目对应于您的一个
    key=value,
    条目。

  • set -f
    禁用路径名扩展,这样如果您的条目之一只是
    *
    它不会转换为文件列表。
    set +f
    重新启用路径名扩展。

  • "${tmp[@]%,}"
    扩展为单词列表,每个
    tmp
    元素一个,如果有尾随逗号,则删除。

  • ${s%%=*}
    作为
    s
    的开头扩展到第一个等号(排除),或者扩展到完整的
    s
    如果它不包含任何等号。
    ${s#*=}
    扩展为
    s
    的结尾,从第一个等号(排除)开始,或者如果不包含任何等号,则扩展到完整的
    s

  • 如果您的键和值本身包含等号,则在第一个遇到等号时完成它们之间的拆分:

    a=b=c=d
    条目被视为“部门名称
    a
    具有代码
    b=c=d
    ”。如果您更喜欢相反的方式(部门
    a=b=c
    有代码
    d
    )只需将
    arr["${s%%=*}"]="${s#*=}"
    替换为
    arr["${s%=*}"]="${s##*=}"
    .


0
投票
#!/bin/bash

deptCodeArray="Information Technology=IT,Marketing=MA,Finance=FI,"

departmentName="Information Technology"

# V1
deptCode=$( echo "$deptCodeArray" | grep -Eo "$departmentName=.+," | cut -d'=' -f2 | cut -d',' -f1 )
echo "V1 $deptCode"

# V2
deptCode=$( echo "$deptCodeArray" | sed "s/.*$departmentName=//;s/,.*//"  )
echo "V2 $deptCode"

V1

  • sed
    删除 departmentName 之前的所有内容。
  • cut
    只保留
    =
    ,
  • 之间的内容

V2

  • sed
    打印 departmentName 和以下
    =
  • 之间的所有内容

注意

  • 我稍微修改了 deptCodeArray,将其放在一行中,并在所有项目(甚至最后一项)后加上逗号。

0
投票

这是一种使用 bash 的

=~
运算符的方法,它将其右侧的字符串视为正则表达式。此示例不使用数组,除了
BASH_REMATCH
(一个内置数组,其成员由
=~
运算符分配),并且应该在 macOS 的 bash 中工作:

#!/bin/bash

# The variable name is misleading. This isn't a bash array
deptCodeArray="
Information Technology=IT,
Marketing=MA,
Finance=FI
"

departmentName="Information Technology"

[[ $deptCodeArray =~ $'\n'"$departmentName"=([^$'\n',]*) ]]
deptCode=${BASH_REMATCH[1]}

echo "$deptCode"

有关

=~
运算符的更多信息,请参阅 Conditional Constructs,以
[[…]]
开头的部分。对于
$'…'
构造,请参见 ANSI-C 引用


0
投票

在 bash v3.2 下:

.1 解析你的

$deptCodeArray

deptCodeArray="
Information Technology=IT,
Marketing=MA,
Finance=FI
"

while IFS== read field value;do
    [ -n "$value" ] && printf -v Arry_${field// /_} '%s' "${value%,}"
done <<<"$deptCodeArray"

然后,这是前面命令创建的数组名称:

printf '[%s]\n' "${!Arry_@}"
[Arry_Finance]
[Arry_Information_Technology]
[Arry_Marketing]
declare -p "${!Arry_@}"
declare -- Arry_Finance="FI"
declare -- Arry_Information_Technology="IT"
declare -- Arry_Marketing="MA"

.2 展示内容:

for var in Information\ Technology Marketing Finance ;do
    nvar=Arry_${var// /_}
    printf '%-25s: %s\n' "$var" "${!nvar}"
done
Information Technology   : IT
Marketing                : MA
Finance                  : FI
© www.soinside.com 2019 - 2024. All rights reserved.