Split string into two levels

Viewed 124

I have the following string

my_str="A:Apple|B:Ball|C:Cat"

and I want to echo the following

A for Apple
B for Ball
C for Cat

The code I use is

IFS="|"
delimiter=':'
my_str="A:Apple|B:Ball|C:Cat"
for pair in ${my_str}; do
  #echo "${pair}"
  s=$pair$delimiter
  var1=${s%%"$delimiter"*}
  var2=${s#*"$delimiter"}
  echo "${var1} for ${var2}"
done

But the output I get is

A for Apple:
B for Ball:
C for Cat:

Could someone help me remove the extra delimiter appended at the end?

4 Answers

bash's read provides an option (-d) for customizing the line delimiter, you can use it in conjunction with IFS.

while IFS=':' read -r -d '|' k v; do
    printf '%s for %s\n' "$k" "$v"
done <<< ${my_str%|}'|'

1st solution: Could you please try following.

echo "$my_str" | awk -F'|' '{gsub(/:/," for ");for(i=1;i<=NF;i++){print $i}}'

2nd solution: Using gsub fair warning, written and tested with shown samples only.

echo "$my_str" | awk '{gsub(/:/," for ");gsub(/\|/,"\n")} 1'

Output will be as follows.

A for Apple
B for Ball
C for Cat

Use two calls to read: one to split the line into an array, the other to split each element of the array.

my_str="A:Apple|B:Ball|C:Cat"

IFS="|" read -a pairs <<< "$my_str"
for pair in "${my_str[@]}"; do
    IFS=: read letter object <<< "$pair"
    printf '%s for %s\n' "$letter" "$object"
done

Using gnu-awk:

awk -F ':|\n' -v RS='|' '{print $1, "for", $2}' <<< "$my_str"

A for Apple
B for Ball
C for Cat

For POSIX awk, use this:

awk -F '[:|]' 'NF%2 == 0{for (i=1; i<=NF; i+=2) print $i, "for", $(i+1)}' <<< "$my_str"
Related