仅使用bash将单个字符串拆分为字符数组


9

我想只使用bash 拆分'hello'h e l l o数组,我可以用sed来做,sed 's/./& /g'但是我想知道当我不知道分隔符是什么,或者分隔符是任意的时,如何在Bash中将字符串拆分成数组单个字符。我不认为我不能${i// /}没有创造力,因为分隔符是一个未知数,我也不认为表达式接受正则表达式。我尝试将BASH_REMATCH与[[string =〜([az]。)。*]]结合使用,但是它没有按预期工作。仅使用bash来完成某种string.split()行为的正确方法是什么?原因是我试图在所有bash中编写rev实用程序:

  while read data; do
  word=($(echo $data|tr ' ' '_'|sed 's/./& /g'))
  new=()
  i=$((${#word[@]} - 1))
  while [[ $i -ge 0 ]]; do
    new+=(${word[$i]})
    (( i-- ))
  done
  echo ${new[@]}|tr -d ' '|tr '_' ' '
  done

但是我使用了tr和sed,我想知道如何正确进行分割,然后将其修复为bash。纯娱乐。


给定它的大小,堆栈溢出上必须有跨站点重复项。Bash是一个候选者:将字符串拆分为字符数组
彼得·莫滕森

[[ $string =~ ${string//?/(.)} ]]BASH_REMATCH[]根据需要设置,请参阅我对彼得·莫滕森(Peter Mortensen)链接的问题的回答以获取解释。
mr.spuratic

Answers:


12
s="hello"
declare -a a   # define array a
for ((i=0; i<${#s}; i++)); do a[$i]="${s:$i:1}"; done
declare -p a   # print array a in a reusable form

输出:

声明-aa ='([[0] =“ h” [1] =“ e” [2] =“ l” [3] =“ l” [4] =“ o”)'

或(请注意评论)

s="hello"
while read -n 1 c; do a+=($c); done  <<< "$s"
declare -p a

输出:

声明-aa ='([[0] =“ h” [1] =“ e” [2] =“ l” [3] =“ l” [4] =“ o”)'

1
第二个是不错的,但是它只能工作(在这种情况下),因为您没有引用“ $ c”,因此它将删除空格并以$ s扩展星号。
rici 2015年

2
第二个选项应该是: while read -N 1 c; do a+=("$c"); done <<< "$s"。在-N允许读甚至换行符和引号("$c")避免路径名扩展(和其他一些问题)。

1
当然,如果必须更正最后一个换行符,请将给定的行更改为:while read -N 1 c; do a+=("$c"); done <<< "$s"x,然后删除最后一个换行符并添加x : unset a[${#a[@]}-1]; unset a[${#a[@]}-1]

4

要将字符串拆分为字符数组(使用空定界符),您可以:

str='hello'
arr=()
i=0
while [ "$i" -lt "${#str}" ]; do
  arr+=("${str:$i:1}")
  i=$((i+1))
done

printf '%s\n' "${arr[@]}"

使用除null以外的定界符,您可以:

set -f
str='1,2,3,4,5'
IFS=',' arr=($str)
printf '%s\n' "${arr[@]}"

如果IFS可以设置,则可以执行以下操作:IFS=',' arr=($str)
muru 2015年

2
@muru:在这种情况下,您将陷入困境。更新了禁用glob。
cuonglm

@BinaryZebra:啊,是的,我的意思不好,缺少报价。修复它,谢谢。
cuonglm

2

只是为了好玩(和其他shell)其他变体:

word=hello
unset letter
while [ ${#word} -gt 0 ]
do
    rest=${word#?}
    letter[${#letter[*]}]=${word%$rest}
    word=$rest
done

并检查

for l in "${!letter[@]}"
do
    echo "letter [$l] = ${letter[l]}"
done

将打印

letter [0] = h
letter [1] = e
letter [2] = l
letter [3] = l
letter [4] = o

0

方法1:

Oneliner:

s="hello"
for ((i=0;i<${#s};i++)); do result[$i]="${s:i:1}"; done
echo ${result[@]}

扩展代码:

s="hello"                   # Original string.

for ((i=0;i<${#s};i++)); do # For i=0; i<(length of s); i++
    result[$i]="${s:i:1}"       # result[i] is equal to the i th character of $s
done                        # End of the loop

echo ${result[@]} # Print all elements of $result.

方法2:

Oneliner:

s="hello"
var=($(while read -n 1; do printf "$REPLY "; done <<< "$s"))
echo "${var[@]}"

扩展代码:

s="hello" # Original string.

while read -n 1; do # Read chraracter by character the string.
    space_separated=$(printf "$space_separated $REPLY") # $space_separated is equal to it plus the current character.
done <<< "$s" # Pass the string to the loop

result=($space_separated) # Split $space_separated into an array.

echo "${result[@]}" # Print all elements of $result.

感谢@cuonglm的建议。
实际上,您可以$REPLYread读取输入的地方使用默认变量。


1
您可以使用$REPLY代替char变量。
cuonglm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.