Awk: Storing string in array(triangular form)

I have a string like below. Now i want to split this string like below and put the value in the array using awk. I am able to do it using bash but getting no clue for doing it in awk

O/P

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  

Bash code

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[@]}"

Hello siramitsharma,

If I understood your requirement correctly, could you please try following and let me know if this helps you.

echo "014387650" | awk '{n=split($0, A,"");if(A[1]==0){e=1};for(i=1;i<=n;i++){while(q<=i){W=W?W A[q]:A[q];q++};if(e && i>1){W=0 W};print "A[" i-1 "]=" W;W="";q=1}}'

Output will be as follows.

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
 

Thanks,
R. Singh

1 Like

Thanks ravinder, but i need to store the same in array which is being mentioned in my bash code & not explicitly printing like the one you mentioned,i.e, if i access A[0] then i should get value 0, if i access A[1] then i should get value 01 & so on. Can you please advice accordingly?

Hello siramitsharma,

Your question's answer lies in my previous post itself, split function used for same only, Here I am taking an array named A in split and giving delimiter as "" means NULL, so it's syntax is split(Line, array_name,delimiter) . So once elements store into array A you could access them as follows for an example.

 echo "014387650" | awk '{split($0, A,"");print A[1]}'
 0
 

We need to note here split created array's element count from 1 unlike the usual arrays where element count starts from 0. Let me know if you have any queries here.

Thanks,
R. Singh

Thanks Ravinder, i have done some modifications and i am able to achieve what i wanted. Btw i have single query for below code logic, can you please throw some light on this.

if(A[1]==0)
{
e=1
}

What you are trying to do isn't really clear yet. Perhaps this will give you an idea of how to do some of the things one could guess might do what you're trying to do:

#!/bin/bash
# If you're trying to produce the output you say your bash script prints (even
# though that is not the output your script produces):
echo 014387650 |
awk '{for(i = 1; i <= length($1); i++) printf("A[%d]=%.*s\n", i - 1, i, $1) }'

# If you're trying to change your existing function to use awk (and print what
# your current script prints):
triangle_split() {
	echo "$1" |
	awk '{for(i = 1; i <= length($1); i++) printf("%.*s\n", i, $1)}'
}
A=($(triangle_split 014387650))
printf '%s\n' "${A[@]}"

# If you're trying to create an array in awk instead of a bash array:
echo 014387650 |
awk '{	# Create array:
	for(i = 0; i < length($1); i++)
		A = substr($1, 1, i + 1)
	# Do whatever you want with the array (in this case, print it)...
	for(i = 0; i < length($1); i++)
		printf("A[%d]=%s\n", i, A)
}'

Note that using awk instead of shell built-ins as a replacement for your current shell function will be a LOT slower. The output from the above script is:

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
01
014
0143
01438
014387
0143876
01438765
014387650
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 want to try this on a Solaris/SunOS system, change awk in all of these cases to /usr/xpg4/bin/awk or nawk .

Hello siramitsharma,

Following is the complete explanation for post above, which may help you to understand the code.

echo "014387650"          ####### using echo to print the string provided by OP in POST.
|                         ####### Using | to send previous command's standard output as standard input to next command.
awk '{n=split($0, A,"");  ####### using split function here to split the elements of line into an array named A and whose delimiter is NULL. Also taking the count of elements in array A into variable named n.
if(A[1]==0){              ####### Checking here if very first element of array or very first digit of line is 0, if it is 0 then later when we append all the elements it is not showing them in that variable like 01, 014 etc it shows rather 1, 14 so only checking it here itself.
e=1};                     ####### Setting variable named e's value to 1 here.
for(i=1;i<=n;i++){        ####### starting a loop for which will run till the value of variable n.
while(q<=i){              ####### Starting a while loop which will till the value of q is equal to variable's i.
W=W?W A[q]:A[q];q++};     ####### Here I am taking values into variable named W, so each time while loop will run it will append values into variable W, then incrementing the value of q to make loop running correctly.
if(e && i>1){             ####### Now checking value of variable named e's value and if it is 1 it means first element of line is 0 and i's value should be greater than 1.
W=0 W};                   ####### If above condition is TRUE then make variable W's value to 0 W.
print "A[" i-1 "]=" W;    ####### printing value of variable W now.
W="";q=1}}'               ####### Nullifying the variable named W and setting q's value to 1 now.
 

Thanks,
R. Singh

Thanks Ravinder & Don.:b:

Great to have you in this forum.:b: