我已经读过如何在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"
说明:
- 首先我们要备份默认/当前的外壳IFS和
bkpIFS="$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]}
。啊,抱歉,忘了回馈
IFS
shell,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])"
说明:
[...]
同样,我们根据正则表达式常量中定义的分隔符组来分割整个输入行,/[...]/
这些分隔符支持现代实现awk
usingsplit
函数。阅读更多在功能部分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[@]}"
这将首先使用 删除到达标准输入的输入数据中的所有()
和,然后用换行符替换逗号并将结果分配给。[]
tr
data
然后我们用它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