Spechal
Spechal

Reputation: 2706

Read into variables from a variable

How can you "read" into variables using IFS and a variable?

I am trying to loop over some data paired by a pipe to be split and worked on. The error I am getting is read: 'site|database': not a valid identifier

SITES="abc|abc xyz|asdf"
for site in $SITES;
do
  IFS="|" read domain database <<< echo $site; # es no bueno mi amigo
  echo "Site: $domain \t\t\t Database: $database";
done;

Am I just doing this the hard way? I am not a native Basher. ;)

Upvotes: 0

Views: 393

Answers (4)

dogbane
dogbane

Reputation: 274522

The problem with your script is that you are not passing the Here String to read correctly. It should be done like this:

IFS=$"|" read domain database <<< "$site" # es no bueno mi amigo

Remember to quote the variable as well.

Your script will then work.

Here is the fixed script:

SITES="abc|abc xyz|asdf"
for site in $SITES
do
  IFS="|" read domain database <<< "$site" # es no bueno mi amigo
  echo -e "Site: $domain \t\t\t Database: $database"
done

It prints:

Site: abc                        Database: abc
Site: xyz                        Database: asdf

Upvotes: 1

William Pursell
William Pursell

Reputation: 212178

IFS will affect word splitting, but the text is still read on a line by line basis. However (assuming none of your records contain a newline), you can do:

SITES="abc|abc xyz|asdf"
echo "$SITES" | tr \| '\012' | while read domain database; do
  echo "Site: $domain \t\t\t Database: $database";
done

To clarify the first sentence, consider the behavior of the following:

echo "$SITES" | while read a b c; do echo "a=$a, b=$b"; done

and

echo "$SITES" | while IFS=\| read a b c; do echo "a=$a, b=$b"; done

Upvotes: 0

Mat
Mat

Reputation: 206659

You're mixing two syntaxes:

read a b <<<$variable

and

read a b < <(command)

I'd try this (without messing with $IFS):

read domain database <<<${site/|/ }

Upvotes: 1

ruakh
ruakh

Reputation: 183211

I think it's simpler to write:

SITES="abc|abc xyz|asdf"
for site in $SITES
do
  domain=${site%|*}      # removes everything from '|' onward
  database=${site#*|}    # removes everything up through '|'
  echo "Site: $domain \t\t\t Database: $database"
done

For information on the ${parameter%word} and ${parameter#word} notations, see §3.5.3 Shell Parameter Expansion in the Bash Reference Manual.

Upvotes: 0

Related Questions