3

I have a string like below. str='014387650' Now i want to split this string like below and put the value in the array.

A[0]=0  
A[1]=01  
A[2]=014  
A[3]=0143  
A[4]=01438  
A[5]=014387  
A[6]=0143876  
A[7]=01438765  
A[8]=014387650  
3
  • the question is not clear , you want the string '014387650 to put in the array A? using bash? or you want to populate every index of the array A as you have written above?
    – Ijaz Ahmad
    Jan 4 '16 at 5:50
  • yes i want to put the string in the array A using bash in unix platform. Jan 4 '16 at 5:56
  • ok , check the answer , i did it for both the cases
    – Ijaz Ahmad
    Jan 4 '16 at 6:28
5

The following should work in bash:

str='014387650'
arr=()
for ((i=0; i<${#str}; i++)); do
    arr+=("${arr[i-1 < 0 ? 0 : i-1]}${str:$i:1}")
done

The result:

$ printf '<%s>\n' "${arr[@]}"
<0>
<01>
<014>
<0143>
<01438>
<014387>
<0143876>
<01438765>
<014387650>
1
  • 1
    I'm confused why you refer back to the previous element instead of just building up the split range on str. It's not wrong, but it seems convoluted to me.
    – kojiro
    Jan 4 '16 at 12:08
1

Explicit declaration of an array is done using the declare built-in:

  declare -a ARRAYNAME 

Array variables may also be created using compound assignments in this format:

  ARRAY=(value1 value2 ... valueN) 

in your case:

  #!/bin/bash
  str='014387650'
  declare -a A
  for (( c=0; c<${#str}; c++ ))
  do
    A[c]=`echo ${str:0:$(( $c + 1 ))}`
    echo "A[$c]="${A[$c]} 
  done

output:

   A[0]=0
   A[1]=01
   A[2]=014
   A[3]=0143
   A[4]=01438
   A[5]=014387
   A[6]=0143876
   A[7]=01438765
   A[8]=014387650

if you just want to put the string in an array:

   declare -a A
   str=014387650
   A=${str[*]}
   echo ${A[*]}
   014387650
   echo ${A[3]}
   4
4
  • 2
    you don't need the `echo
    – meuh
    Jan 4 '16 at 6:59
  • yes , its just for showing the output , if you dont want to show the output , you dont need that
    – Ijaz Ahmad
    Jan 4 '16 at 8:00
  • 2
    I meant you can do A[c]=${str:0:$(( $c + 1 ))} without the `echo` part.
    – meuh
    Jan 4 '16 at 8:06
  • ya , you are right , it should also work that way.
    – Ijaz Ahmad
    Jan 4 '16 at 8:07
1

Another way:

triangle_split() {
  _len=1
  while [ "$_len" -le "${#1}" ]; do
    printf '%.*s\n' "$_len" "$1"
    : "$((_len+=1))"
  done
}

IFS='
'
A=($(triangle_split 014387650))

printf '%s\n' "${A[@]}"
14
  • Could you please explain below line. printf '%.*s\n' "$_len" "$1" : "$((_len+=1))" Jan 4 '16 at 6:47
  • The first argument to printf '%.*s\n' is maximum bytes to be printed, here it's $_len variable. $((_len+=1)) increase _len by one. So you got the first, the second, ... until you got the whole string.
    – cuonglm
    Jan 4 '16 at 6:56
  • maybe weirder, but: len=0;while printf "%.$((len+=1))s\n%.d" "$1" "0$((len<${#1}?0:8))"; do :;done 2>/dev/null
    – mikeserv
    Jan 4 '16 at 9:45
  • 1
    @mikeserv: tricky, maybe "0$((len<${#1}?0:8))" should become "0$((len<${#1}?0:$((${#1}-1))))" for more dynamic?
    – cuonglm
    Jan 4 '16 at 9:53
  • 1
    ok. printf is spec'd for interpreting it's arguments as C integer constants. POSIX (apparently aligned w/ the ANSI standard) specs integer constants thus: A decimal constant begins with a non-zero digit, and consists of a sequence of decimal digits. An octal constant consists of the prefix '0' optionally followed by a sequence of the digits '0' to '7' only... [EINVAL] No conversion could be performed.
    – mikeserv
    Jan 5 '16 at 2:19
1

Obvious approach: let's loop downward through the array, chopping one character at a time from the tail of a string variable which is assigned to the successive elements:

#!/bin/bash

str="014387650"

while [ ${#str} -gt 0 ] ; do
  A[$((${#str}-1))]=$str
  str=${str%?}
done

printf "%s\n" ${A[*]}

Output:

0
01
014
0143
01438
014387
0143876
01438765
014387650

Since we are Bash-specific, we might as well rephrase the logic using a for loop:

#!/bin/bash

str="014387650"

for (( i=${#str} - 1; i >= 0; i-- )); do
  A[$i]=$str
  str=${str%?}
done

printf "%s\n" ${A[*]}
1
  • is it more obvious than the other one? i would think you would just flip the sign.
    – mikeserv
    Jan 5 '16 at 5:25
0

You might do:

set --; src=014387650 OPTIND=1 tgt=
while   getopts : na -"$src"
do      tgt=$tgt$OPTARG
        set "$@" "A[$#]=$tgt"
done;   printf   %s\\n "$@"

A[0]=0
A[1]=01
A[2]=014
A[3]=0143
A[4]=01438
A[5]=014387
A[6]=0143876
A[7]=01438765
A[8]=014387650
0

Obvious approach: fill the array backwards, and chop the last character of the string as we go:

#!/bin/bash

str="014387650"

i=${#str}

while [ $i -gt 0 ] ; do
  A[$((--i))]=$str
  str=${str%?}
done

printf "%s\n" ${A[*]}

Output:

0
01
014
0143
01438
014387
0143876
01438765
014387650
0

Maybe this will help:

#!/bin/bash

a="014387650"

i=0; unset -v A B
while (( i<${#a} ))
do    A[i]=${a:0:i+1}
      B+=("A[$i]=${A[i++]}")
done

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

Output:

A[0]=0
A[1]=01
A[2]=014
A[3]=0143
A[4]=01438
A[5]=014387
A[6]=0143876
A[7]=01438765
A[8]=014387650

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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