如何在shell脚本中将字符串转换为数组

如何在shell脚本中将字符串转换为数组

我已经读过如何在bash中将字符串拆分为数组但这个问题对我来说似乎有点不同,所以我会用我的数据来问。

我有来自 STDIN 的这条线:

(5,[a,b,c,d,e,f,g,h,i,j])

五个是我的组 ID,字母是数组的值(组数据)。我需要将组 ID 放入 var 并将字母放入我可以使用的东西中IFS=',' read -r -a array <<< "$tline"

答案1

bkpIFS="$IFS"

IFS=',()][' read -r -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j])"
echo ${array[@]}    ##Or printf "%s\n" ${array[@]}
5 a b c d e f g h i j

IFS="$bkpIFS"

说明:

  • 首先我们要备份默认/当前的外壳IFSbkpIFS="$IFS";
  • 然后我们将 IFS 设置为一组分隔符,()、 ,][意味着IFS=',()]['我们的输入字符串可以用这些分隔符中的一个或多个分隔。

  • 接下来read -r -a array读取该行并将其拆分为一个数组,array仅根据上面定义的 IFS 从传入的输入字符串中调用这里的字符串方法。该-r选项用于告诉命令如果输入时read不要对反斜杠进行扩展。\

    IFS=',()][' read -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j,\,k])"
    echo ${array[@]}
    5 a b c d e f g h i j ,k
    

    看到最后,k这是由于输入中有反斜杠而read没有其-r选项引起的。

  • 我们echo ${array[@]}正在打印数组的所有元素。看$* 和 $@ 有什么区别?吉尔斯的回答关于${array[@]}那里有更多细节。

  • 还有printf "%s\n" ${array[@]}其他方法来打印数组元素。

  • printf "%s\n" ${array[INDEX]}现在您可以使用 或打印数组的特定元素echo ${array[INDEX]}

  • 啊,抱歉,忘了回馈IFSshell,IFS="$bkpIFS":)

或者使用awk及其split功能。

awk '{split($0,arr,/[][,)(]/)} 
    END{for (x in arr) printf ("%s ",arr[x]);printf "\n"}' <<<"(5,[a,b,c,d,e,f,g,h,i,j])"

说明:

  • [...]同样,我们根据正则表达式常量中定义的分隔符组来分割整个输入行,/[...]/这些分隔符支持现代实现awkusingsplit函数。阅读更多在功能部分split()

  • 接下来,END{for (x in arr) printf ("%s ",arr[x]); ...}我们循环调用数组arr并打印它们相应的值。x这里指向指数数组arr元素。阅读更多关于awk的 BEGIN/END 规则

侧面重定向到如何在 bash 中向数组添加/删除元素?

答案2

data=$(tr -d '[]()' | tr ',' '\n')

readarray -t -n 1 group   <<<"$data"
readarray -t -s 1 letters <<<"$data"

printf 'group = %s\n' "$group"
printf 'data: %s\n' "${letters[@]}"

这将首先使用 删除到达标准输入的输入数据中的所有()和,然后用换行符替换逗号并将结果分配给。[]trdata

然后我们用它readarray来解析这些数据。

第一次调用只会读取第一个条目(带有-n 1)并将其分配给变量group

第二次调用readarray将跳过第一个条目(带有-s 1)并将剩余条目分配给数组letters

从每个条目中删除-t实际的换行符。

尽管group这里是一个数组,但它只包含一个元素,您可以将其用作$group.

$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
group = 5
data: a
data: b
data: c
data: d
data: e
data: f
data: g
data: h
data: i
data: j

以下保留字符串中的逗号并readline使用它们来分隔条目,但由于某种原因,最后一个元素letters末尾有一个换行符:

data=$(tr -d '[]()')
readarray -d, -t -s 1 letters <<<"$data"

printf '>%s<\n' "${letters[@]}"

跑步:

$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
>a<
>b<
>c<
>d<
>e<
>f<
>g<
>h<
>i<
>j
<

答案3

POSIXly:

string='(5,[a,b,c,d,e,f,g,h,i,j])'
set -o noglob
IFS=',['
string=${string#'('}
string=${string%'])'}
set -- $string''
gid=$1; shift 2
printf '%s\n' "gid=$gid; group-data:"
printf '   <%s>\n' "$@"

它应该适用于组数据字段的任何值,甚至是那些带有换行符的值。

答案4

我们可以使用工具去除标点符号sed,因此您只能从该行中得到数字和字母:

a="(5,[a,b,c,d,e,f,g,h,i,j])"

echo $a | sed 's/[[:punct:]]/ /g'

输出:

5  a b c d e f g h i j 

相关内容