Split a string by some separator in bash?

Pure bash solution, using IFS and read. Note that the strings shouldn't contain $'\2' (or whatever else you use for IFS, unfortunately $'\0' doesn't work, but e.g. $'\666' does):

#!/bin/bash

split_by () {
    string=$1
    separator=$2

    tmp=${string//"$separator"/$'\2'}
    IFS=$'\2' read -a arr <<< "$tmp"
    for substr in "${arr[@]}" ; do
        echo "<$substr>"
    done
    echo
}


split_by '1--123--23' '--'
split_by '1?*123' '?*'

Or use Perl:

perl -E 'say for split quotemeta shift, shift' -- "$separator" "$string"

Pure POSIX shell:

string="1--123--23"
del="--"

while test "${string#*$del}" != "$string" ; do
  echo "${string%%$del*}"
  string="${string#*$del}"
done
echo "$string"

Note that * or ? need to be escaped in the delimiter: del='\*'


Simply with awk:

str="1--123--23"
awk -F'--' '{ for(i=1;i<=NF;i++) print $i }' <<< $str

The output:

1
123
23

Another short Python solution:

splitter.py script:

import sys
print('\n'.join(sys.argv[2].split(sys.argv[1])))

arguments order:

  • sys.argv[0] - script name (i.e. splitter.py)

  • sys.argv[1] - substring separator

  • sys.argv[2] - input string

Usage:

python splitter.py "?*" "1?*123"
1
123

python splitter.py "--" "1--23--123"
1
23
123