Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to split 'hello' into h e l l o in an array using only bash, I could do it in sed with sed 's/./& /g' but I want to know how to split a string into an array in Bash when I do not know what the delimiter would be, or the delimiter is any single character. I don't think I can use ${i// /} without some creativity because the delimiter is an unknown, and I don't think that expression accepts regex. I tried using BASH_REMATCH with [[ string =~ ([a-z].).* ]] but it doesn't work as I expected. What is the proper way to use only bash to accomplish a string.split() type of behavior? The reason is that I am trying to write the rev utility in all bash:

  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

But I used tr and sed, I want to know how to do the split properly and then I will fix it to be all bash. Just for fun.

share|improve this question
    
There must be cross-site duplicates on Stack Overflow, given the size of it. One candidate is Bash: Split string into character array. –  Peter Mortensen yesterday

4 Answers 4

up vote 4 down vote accepted
s="hello"
declare -a a
for ((i=0; i<${#s}; i++)); do a[$i]="${s:$i:1}"; done
declare -p a

Output:

declare -a a='([0]="h" [1]="e" [2]="l" [3]="l" [4]="o")'

or

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

Output:

declare -a a='([0]="h" [1]="e" [2]="l" [3]="l" [4]="o")'
share|improve this answer
    
The second one is nice but it only works (in this case) because you don't quote "$c", so it will drop whitespace and expand stars in $s. –  rici 23 hours ago

To split string into array of characters, with null delimiter, you can:

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

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

With delimiter other than null, you can:

str='1,2,3,4,5'
IFS=',' read -r -a arr <<<"$str"
printf '%s\n' "${arr[@]}"

or:

set -f
str='1,2,3,4,5'
IFS=',' arr=($str)
printf '%s\n' "${arr[@]}"
share|improve this answer
    
If IFS can be set, then you can just do: IFS=',' arr=($str). –  muru yesterday
2  
@muru: You will be stucked with glob in that case. Updated with disabling glob. –  cuonglm yesterday

Just for fun (and other shells) other variant:

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

And check

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

will print

letter [0] = h
letter [1] = e
letter [2] = l
letter [3] = l
letter [4] = o
share|improve this answer

Method 1:

Oneliner:

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

Expanded code:

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.

Method 2:

Oneliner:

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

Expanded code:

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.

Thanks to @cuonglm by it's suggestion.
Effectively, you can use $REPLY that is the default varible where read reads the input.

share|improve this answer
1  
You can use $REPLY instead of char variable. –  cuonglm yesterday
    
@cuonglm: Thanks! –  Helio yesterday

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.