Wednesday, October 2, 2019

shell - How do I split a string on a delimiter in Bash?



I have this string stored in a variable:




IN="bla@some.com;john@home.com"


Now I would like to split the strings by ; delimiter so that I have:



ADDR1="bla@some.com"
ADDR2="john@home.com"



I don't necessarily need the ADDR1 and ADDR2 variables. If they are elements of an array that's even better.






After suggestions from the answers below, I ended up with the following which is what I was after:



#!/usr/bin/env bash

IN="bla@some.com;john@home.com"


mails=$(echo $IN | tr ";" "\n")

for addr in $mails
do
echo "> [$addr]"
done


Output:




> [bla@some.com]
> [john@home.com]


There was a solution involving setting Internal_field_separator (IFS) to ;. I am not sure what happened with that answer, how do you reset IFS back to default?



RE: IFS solution, I tried this and it works, I keep the old IFS and then restore it:



IN="bla@some.com;john@home.com"


OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
echo "> [$x]"
done

IFS=$OIFS



BTW, when I tried



mails2=($IN)


I only got the first string when printing it in loop, without brackets around $IN it works.


Answer



You can set the internal field separator (IFS) variable, and then let it parse into an array. When this happens in a command, then the assignment to IFS only takes place to that single command's environment (to read ). It then parses the input according to the IFS variable value into an array, which we can then iterate over.




IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
# process "$i"
done


It will parse one line of items separated by ;, pushing it into an array. Stuff for processing whole of $IN, each time one line of input separated by ;:



 while IFS=';' read -ra ADDR; do
for i in "${ADDR[@]}"; do

# process "$i"
done
done <<< "$IN"

No comments:

Post a Comment

hard drive - Leaving bad sectors in unformatted partition?

Laptop was acting really weird, and copy and seek times were really slow, so I decided to scan the hard drive surface. I have a couple hundr...