1

Suppose I have a string with pipe separator:

str="1|2|3|4"

I want them to be assigned to specific variables.

var_a=1
var_b=2
var_c=3
var_d=4

I am doing it in this way:

var_a="`echo $str | cut -d'|' -f1`"
var_b="`echo $str | cut -d'|' -f2`"
var_c="`echo $str | cut -d'|' -f3`"
var_d="`echo $str | cut -d'|' -f4`"

Can this be done in an efficient way? Please suggest.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • Would it be ok to use an array instead of five different variables? – Socowi Jul 10 '18 at 14:18
  • BTW, `echo $str` is itself buggy; `echo "$str"` is slightly better (won't replace a `*` with a list of filenames, for example); `printf '%s\n' "$str"` is *much* better (works correctly with all possible values, including `-n` or `-e`, which some versions of `echo` will consume). See [BashPitfalls #14](http://mywiki.wooledge.org/BashPitfalls#echo_.24foo), and the APPLICATION USAGE section of [the POSIX `echo` specification](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html). – Charles Duffy Jul 10 '18 at 14:29

2 Answers2

4

It is better to use an array to store individual delimited values:

str="1|2|3|4"
IFS='|' read -ra arr <<< "$str"

#examine array values
declare -p arr

declare -a arr='([0]="1" [1]="2" [2]="3" [3]="4")' 

To loop through array, use:

for i in "${arr[@]}"; do echo "$i"; done

1
2
3
4
anubhava
  • 761,203
  • 64
  • 569
  • 643
3
IFS='|' read -r var_a var_b var_c var_d rest <<<"$str"

rest is the variable that gets further columns after the first four, should any others exist. If you just want to discard them, the conventional name to use for a placeholder variable is _.

This is covered in detail in BashFAQ #1: How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441