gpt4 book ai didi

Bash:使用变量作为数组名称

转载 作者:行者123 更新时间:2023-11-29 09:03:23 25 4
gpt4 key购买 nike

我正在解析一个日志文件并使用行号和最后一个字段(总登录时间)为每个用户创建关联数组。日志文件的行如下所示:

jww3321   pts/2        cpe-76-180-64-22 Mon Oct 18 23:29 - 00:27  (00:58)
jpd8635 pts/1 cpe-74-67-131-24 Mon Oct 18 23:22 - 03:49 (04:26)

第一个字段 (jww3321) 将是数组名称,数组中的第一个条目将是 (1,00:58),下一个将是 (2,(用户的下一次))。为了获得正确的键,我需要保存列表的长度,并在将下一个值添加到用户数组时为其添加一个。到目前为止,我的代码如下所示:

cat lastinfo.txt | while read line
do
uname=`echo "$line" | awk '{print $1;}'`
count=`echo "${#$uname[@]}"`
echo "$count"
done

我试过使用间接引用,但我遇到了这个错误:

l8t1: line 7: ${#$uname[@]}: bad substitution

有什么建议吗?

最佳答案

我不确定我是否正确理解了您正在尝试做的事情,特别是“关联”部分(我看不到在何处使用了关联数组),但是这段代码执行了我所理解的您想要的操作做:

#!/bin/bash
while IFS=" " read user time; do
eval "item=\${#$user[@]} ; $user[\$item]=\(\$((\$item + 1)),$time\)"
[[ "${arraynames[@]}" =~ $user ]] || arraynames[${#arraynames[@]}]=$user
done< <(sed -r 's/^ *([[:alnum:]]*) .*\((.*)\)$/\1 \2/')

for arrayname in ${arraynames[@]}; do
eval "array=(\${$arrayname[@]})"
echo "$arrayname has ${#array[@]} entries:"
for item in ${!array[@]}; do
echo "$arrayname[$item] = ${array[$item]}"
done
echo
done

它从标准输入读取。我已经用这样的示例文件对其进行了测试:

    jww3321   pts/2        cpe-76-180-64-22 Mon Oct 18 23:29 - 00:27  (00:58)    jpd8635   pts/1        cpe-74-67-131-24 Mon Oct 18 23:22 - 03:49  (04:26)    jww3321   pts/2        cpe-76-180-64-22 Mon Oct 18 23:29 - 00:27  (01:58)    jpd8635   pts/1        cpe-74-67-131-24 Mon Oct 18 23:22 - 03:49  (05:26)

Output:

    jww3321 has 2 entries:    jww3321[0] = (1,00:58)    jww3321[1] = (2,01:58)    jpd8635 has 2 entries:    jpd8635[0] = (1,04:26)    jpd8635[1] = (2,05:26)

Note that only standard integer-indexed arrays are used. In Bash, as of now, indirect array references in the left side always involve using eval (uuuuuuhhhh, ghostly sound), in the right side you can get away with ${!} substitution and command substitution $().

Rule of thumb with eval: escape what you want to be expanded at eval time, and don't escape what you want to be expanded before eval time. Any time you're in doubt about what ends up being eval'd, make a copy of the line and change eval for echo.

edit: to answer sarnold's comment, a way to do this without eval:

#!/bin/bash
while IFS=" " read user time; do
array=$user[@] array=( ${!array} ) item=${#array[@]}
read $user[$item] <<< "\($(($item + 1)),$time\)"
[[ "${arraynames[@]}" =~ $user ]] || arraynames[${#arraynames[@]}]=$user
done< <(sed -r 's/^ *([[:alnum:]]*) .*\((.*)\)$/\1 \2/')

for arrayname in ${arraynames[@]}; do
array=$arrayname[@] array=( ${!array} )
echo "$arrayname has ${#array[@]} entries:"
for item in ${!array[@]}; do
echo "$arrayname[$item] = ${array[$item]}"
done
echo
done

关于Bash:使用变量作为数组名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8045474/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com