如何在Bash中将一个字符串转换为单个字符数组?

3

我该如何将一个字符串,比如"Hello World!",拆分成单个字符呢?

以上面的例子为例,我想要一个数组,每个值都是单个字符。所以数组内部应该像这样:

{"H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"}


awk -v FS="" ' {printf"{";for(i=1;i<=NF;i++) if(i!=NF)printf """$i"",";print $i"}"}' inputfile 这段代码存在缺陷,因此不作为答案。 - P....
8个回答

4
str="Hello world!"
for (( i=0 ; i < ${#str} ; i++ )) {
    arr[$i]=${str:i:1}
}

#print
printf "=%s=\n" "${arr[@]}"

输出

=H=
=e=
=l=
=l=
=o=
= =
=w=
=o=
=r=
=l=
=d=
=!=

您可以使用以下命令将结果分配到数组中:

mapfile -t array < <(command args)

很遗憾,定义自定义分隔符-d需要使用bash 4.4.+版本。假设,想要使用grep将上述字符串分成两个字符片段。

mapfile -t -d ''  a2 < <(grep -zo .. <<<"$str")
printf "=%s=\n" "${a2[@]}"

输出:

=He=
=ll=
=o =
=wo=
=rl=
=d!=

1

纯 Bash 方法 - 逐个字符遍历字符串并获取子字符串:

#!/bin/bash

declare -a arr
string="Hello World!"
for ((i = 0; i < ${#string}; i++)); do
   # append i'th character to the array as a new element
   # double quotes around the substring make sure whitespace characters are protected 
  arr+=("${string:i:1}")
done

declare -p arr
# output: declare -a arr=([0]="xy" [1]="y" [2]="H" [3]="e" [4]="l" [5]="l" [6]="o" [7]="W" [8]="o" [9]="r" [10]="l" [11]="d" [12]="!")

1
我可以看到有两种方法来实现这个。在纯Bash中,逐个字符迭代字符串并将每个字符添加到数组中:
$ str='Hello World!'
# for (( i = 0; i < ${#str}; ++i )); do myarr+=("${str:i:1}"); done
$ declare -p myarr
declare -a myarr='([0]="H" [1]="e" [2]="l" [3]="l" [4]="o" [5]=" " [6]="W" [7]="o" [8]="r" [9]="l" [10]="d" [11]="!")'

关键元素是子字符串扩展,"${str:i:1}",它扩展为从索引i开始并具有长度1的str子字符串。请注意,这是您不必在此处使用$前缀变量来获取其内容的少数几次之一,因为i在此处处于算术上下文中。
使用外部工具fold
$ readarray -t arr <<< "$(fold -w 1 <<< "$str")"
$ declare -p arr
declare -a arr='([0]="H" [1]="e" [2]="l" [3]="l" [4]="o" [5]=" " [6]="W" [7]="o" [8]="r" [9]="l" [10]="d" [11]="!")'

fold -w 1 命令将输入字符串每行包装为一个字符,readarray 命令按行(-t 选项移除每个元素的换行符)读取其输入到数组中。

请注意,readarray 需要 Bash 4.0 或更高版本。


1

使用数组索引在 bash 中实现这个功能相当简单。只需循环遍历所有字符并将其拾取到数组中即可,例如:

#!/bin/bash

a="Hello World!"

for ((i = 0; i < ${#a}; i++)); do 
    array+=("${a:i:1}")           ## use array indexing for individual chars
done

printf "%s\n" "${array[@]}"       ## output individual chars

示例使用/输出
$ sh bashchar.sh
H
e
l
l
o

W
o
r
l
d
!

3
您没有引用"${array[@]}",这导致空格被忽略掉了 ;) - Benjamin W.
好的,抓住了 :) - David C. Rankin
1
我的意思是在最后一行,${array[@]}如果不加引号会被分成多个部分,空格也会消失。 - Benjamin W.
1
呃,永远不要试图根据直觉进行更正 :) - David C. Rankin

0
为了多样性,这里提供一个纯 Bash 的解决方案,不需要使用数组索引:
string="Hello world"
split=( )
while read -N 1; do
    split+=( "$REPLY" )
done < <( printf '%s' "$string" )

最后一行使用进程替换将printf的输出传递给循环。循环使用read -N 1每次读取一个字符。


0
awk '{ for ( i=1;i<=length($0);i++ ) printf substr($0,i,1)"\n" }' <<< $str
mapfile arry1 < <(echo "$str1")

0

试试这个 -

$v="Hello World!"
$awk  '{n=split($0,a,""); for(i=1;i<=n;i++) {print a[i]}}' <<<"$v"
H
e
l
l
o

W
o
r
l
d
!

0

如果您要生成JSON,请使用方括号而不是花括号,以及jq 而不是Bash:

jq -c -R 'explode|map([.]|implode)' <<<'Hello World!'
["H","e","l","l","o"," ","W","o","r","l","d","!"]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接