我在脚本中有一组部门名称和部门代码。 用户将选择一个部门名称,然后将其分配给一个变量;我需要
# 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,但我在理解如何使它起作用时遇到了一些麻烦,而且我不确定其他方法是否可行。 我也不确定我是否有正确的数组语法。
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##*=}"
.
#!/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 和以下 =
注意
这是一种使用 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 引用
.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