How to print elements between letters bash script?

Hello to all,

May somebody help me to fix my bash code below, I'd like to do it only using loops and if statements is possible.

I the content of the arrays are represented by the following 2 strings, where each character is an element inside the array.

String for case 1:

81UV78UV183UV89800

String for case 2:

8U1UVV78UUV18UU3UV89800

The strings are separated by "U" followed by "V", this is "UV", but sometimes U or V appears alone (not in sequence UV). I want to print the elements between UV concatenated in a single string.

For String 1 the array is 1rst one and the output would be:

81
78
183
89800
 

and I'm only getting 81, 78 and 89800.

for String 2 the array is 2nd one "commented" and the output would be:

8U1
V78U
18UU3
89800

and I'm only getting 8, 78 and 18.

The code I have so far is:

#!/bin/bash
 
#String 1 (81UV78UV183UV89800) represents content of  this array
a[0]=8;a[1]=1;a[2]=U;a[3]=V;a[4]=7;a[5]=8;a[6]=U;
a[7]=V;a[8]=1;a[9]=8;a[10]=3;a[11]=U;a[12]=V;
a[13]=8;a[14]=9;a[15]=8;a[16]=0;a[17]=0;
 
#String 2 (8U1UVV78UUV18UU3UV89800) represents content of  this array
#a[0]=8;a[1]=U;a[2]=1;a[3]=U;a[4]=V;a[5]=V;a[6]=7;a[7]=8;
#a[8]=U;a[9]=U;a[10]=V;a[11]=1;a[12]=8;a[13]=U;a[14]=U;a[15]=3;a[16]=U;
#a[17]=V;a[18]=8;a[19]=9;a[20]=8;a[21]=0;a[22]=0;
 
for (( i=0; i<${#a[@]}; i++))
do
 if [ "${a[$i]}" == "U" ]; then
  c=1
 elif [ "${a[$i]}" == "V" ]; then
  c=0
  if (( ${#buff} > 0 )); then
   echo ${buff}
   buff=""
  fi
 elif (( c == 0 )); then
  buff=${buff}${a[$i]}
 fi
done

PS: The data is stored in arrays initially but I show you the way the data looks in a string for you to understand better. I'm using Cygwin.

Thanks in advance for any help.

Arrays are not a very good way to store this data you could simplify the code by using strings:

STR=81UV78UV183UV89800
for val in ${STR//UV/ }
do
   echo $val
done

Anyway here is the method you want - note the final test as you have no terminating UV in your data:

#!/bin/bash
 
#String 1 (81UV78UV183UV89800) represents content of  this array
#a[0]=8;a[1]=1;a[2]=U;a[3]=V;a[4]=7;a[5]=8;a[6]=U;
#a[7]=V;a[8]=1;a[9]=8;a[10]=3;a[11]=U;a[12]=V;
#a[13]=8;a[14]=9;a[15]=8;a[16]=0;a[17]=0;
a=( 8 1 U V 7 8 U V 1 8 3 U V 8 9 8 0 0 )
 
#String 2 (8U1UVV78UUV18UU3UV89800) represents content of  this array
#a[0]=8;a[1]=U;a[2]=1;a[3]=U;a[4]=V;a[5]=V;a[6]=7;a[7]=8;
#a[8]=U;a[9]=U;a[10]=V;a[11]=1;a[12]=8;a[13]=U;a[14]=U;a[15]=3;a[16]=U;
#a[17]=V;a[18]=8;a[19]=9;a[20]=8;a[21]=0;a[22]=0;
#a=(  8 U 1 U V V 7 8 U U V 1 8 U U 3 U V 8 9 8 0 0 )

for (( i=0; i<${#a[@]}; i++))
do
 if [ "${a}${a[i+1]}" == "UV" ]; then
    ((i++))
    if (( ${#buff} > 0 )); then
           echo ${buff}
           buff=""
    fi
 else
    buff=${buff}${a}
 fi
done
if (( ${#buff} > 0 )); then
   echo ${buff}
fi
1 Like

This is bash. You can do what you want with far less code.

#!/bin/bash

# this outer loop of the code is here to put the strings in array variables
# you do not have to do it this way

for i in 81UV78UV183UV89800  8U1UVV78UUV18UU3UV89800
do 
  declare -a  myarr=( $(echo "$i" | sed 's/UV/ /g')  )  # create the element of the array
  for (( i=0 ; i< ${#myarr[*]} ; i++ ))  # print the elements of the array
  do
     echo ${myarr}
  done
done



1 Like

Thanks so much Chubler_XL for fix my issue. It works this time. :slight_smile:

Thanks Jim for show another way to do it with bash.

Best regards

far less code :

for i in 81UV78UV183UV89800  8U1UVV78UUV18UU3UV89800; do  read -a ar <<<"${i//UV/ }"; printf '%s\n' "${ar[@]}"; done

:smiley:

Hi,

If you don't mind an AWK solution:

for str in 81UV78UV183UV89800  8U1UVV78UUV18UU3UV89800
do
echo $str | awk -F'UV' '{for (i=1;i<=NF;i++)if($i != "")print $i}'
done
81
78
183
89800
8U1
V78U
18UU3
89800

Some more awk

 awk 'gsub(/UV/,"\n")' <<<$str
 awk '{print $1}' RS="UV" <<<$str
 awk '{$1=$1}1' OFS="\n" FS="UV" <<<$str

O/P with sample input

$ echo 81UV78UV183UV89800 | awk 'gsub(/UV/,"\n")'
81
78
183
89800

$ echo 8U1UVV78UUV18UU3UV89800 | awk 'gsub(/UV/,"\n")'
8U1
V78U
18UU3
89800

$ echo 81UV78UV183UV89800 | awk '{print $1}' RS="UV"
81
78
183
89800

$ echo 8U1UVV78UUV18UU3UV89800  | awk '{print $1}' RS="UV"
8U1
V78U
18UU3
89800

$ echo 81UV78UV183UV89800 | awk '{$1=$1}1' OFS="\n" FS="UV"
81
78
183
89800

$ echo 8U1UVV78UUV18UU3UV89800  | awk '{$1=$1}1' OFS="\n" FS="UV"
8U1
V78U
18UU3
89800

This may be a bash ism:

for str in 81UV78UV183UV89800  8U1UVV78UUV18UU3UV89800; do echo "${str//UV/$'\n'}"; done
81
78
183
89800
8U1
V78U
18UU3
89800

Thank you to all of you for share your solutions. The issue is the data is stored in arrays as I showed in first post. I showed strings to represent what is the content of the array. Because of that I was using combination of loops and if statements.

Thanks again.

OK, with array a from your first post, try

A=${a[@]}
A=${A// /}
echo "${A//UV/$'\n'}"
81
78
183
89800

Hi RudiC,

It works just fine either and very short code, nice!

Many thanks again.