0

For a Bash function my_fun, how can I use a delimiter (e.g. ";") to split input into an array of strings?

Example input:

$ my_fun This is ; an example

Example output:

string1: This is
string2: an example

Perhaps using $IFS=';' or the read command?

  • 2
    Does this answer your question? [How do I split a string on a delimiter in Bash?](https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash) – Emanuel P Feb 24 '23 at 04:09
  • It's close, but the input needs to be the parameters of a function. I intend to use it to create SQL queries. – Ivo Treszka Feb 24 '23 at 04:22
  • 2
    `;` is not a good choice. it's a command separator in the shell – oguz ismail Feb 24 '23 at 04:34
  • Thanks for pointing that out. That may have been the cause of my problem. – Ivo Treszka Feb 24 '23 at 05:20
  • 1
    You'll probably have to quote the parameter no matter what you choose as a delimiter. This can be messy if the parameter also *contains* quotes, because quotes of the same type don't nest (i.e. you can't put single-quotes in a single-quoted string without gymnastics, and double-quotes must be escaped inside double-quotes). – Gordon Davisson Feb 24 '23 at 05:40
  • See: [How to be explicit about intentional word splitting?](https://stackoverflow.com/a/62638388/7939871) – Léa Gris Feb 24 '23 at 17:40

3 Answers3

2

Delimiter ; needs to be escaped with a backslash (\;) to prevent Bash from interpreting it as a command separator :

my_fun() {
  IFS=';' read -ra arr <<< "$@"
  for i in "${!arr[@]}"; do
    echo "string$i: ${arr[i]}"
  done
}

Output :

$ my_fun This is\;an example
string0: This is
string1: an example
Wahyu Kristianto
  • 8,719
  • 6
  • 43
  • 68
1

With the help of the comments, here's my solution:

split_str() {
    IFS=";" read -ra arr <<< "$*"
    s1="${arr[0]}"
    s2="${arr[1]}"
    echo "s1: $s1"
    echo "s2: $s2"
}

Example:

$ split_str "This is;a test"
s1: This is
s2: a test

The parameters are to be quoted, so it doesn't matter whether the delimiter is a command separator in the shell.

0

No need to loop, no need to read, simply assign an array with IFS set to ;:

my_fun() { IFS=';' arr=( $@ ); printf '|%s|\n' "${arr[@]}"; }
my_fun "foo ; bar ; baz"
|foo |
| bar |
| baz|

As noted in comments this may break if the input contains glob patterns (like *): pathname expansion would apply. If this can happen you can enable/disable the noglob option:

my_fun() { set -f; IFS=';' arr=( $@ ); set +f; printf '|%s|\n' "${arr[@]}"; }
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51