I have a string in the next format

id;some text here with possible ; inside

and want to split it to 2 strings by first occurrence of the ;. So, it should be: id and some text here with possible ; inside

I know how to split the string (for instance, with cut -d ';' -f1), but it will split to more parts since I have ; inside the left part.


cut sounds like a suitable tool for this:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

But read is even more suitable:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"

bash-4.2$ echo "$string"
some text here with possible ; inside
  • 3
    Great! It works like a charm! I will select the read since i'm using bash. Thank you @manatwork! – gakhov Oct 30 '12 at 13:45
  • The cut approach will only work when "$s" doesn't contain newline characters. read is in any Bourne-like shell. <<< is in rc, zsh and recent versions of bash and ksh93 and is the one that is not standard. – Stéphane Chazelas Oct 30 '12 at 14:24
  • Oops, you are right @StephaneChazelas. My mind was at -a for some reason when mentioning bash's read. (Evidently of no use here.) – manatwork Oct 30 '12 at 14:34
  • I forgot to mention that the read approach doesn't work if $s contains newline characters either. I've added my own answer. – Stéphane Chazelas Oct 30 '12 at 14:37
  • 1
    I would like to emphasize the trailing dash in -f 2- in the string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string" command. This is what ignores the rest of the delimiters in the string for the printout. Not obvious when looking at the man page of cut – Steen Jun 27 '14 at 8:14

With any standard sh (including bash):

case $s in

read based solutions would work for single character (and with some shells, single-byte) values of $sep other than space, tab or newline and only if $s doesn't contain newline characters.

cut based solutions would only work if $s doesn't contain newline characters.

sed solutions could be devised that handle all the corner cases with any value of $sep, but it's not worth going that far when there's builtin support in the shell for that.


As you have mentioned that you want to assign the values to id and string

first assign your pattern to a variable(say str)

    str='id;some text here with possible ; inside'

Now you have your values in respective variables

  • if you are getting your pattern from a command then use set -- some_command ,then your pattern will get stored in $1 and use the above code with 1 instead of str – user1678213 Oct 31 '12 at 12:43
  • 1
    How is this answer different from @StephaneChazelas? – Bernhard Oct 31 '12 at 12:50
  • 2
    Should be ${str%%;*} for id and ${str#*;} for str (with the asterisks). This is an old answer though so perhaps this worked on older versions of bash, but these changes were required for me on bash 4.2+ (and possibly earlier, I did not test). – fquinner Dec 9 '20 at 12:48

Solution in standard bash:

    text='id;some text here with possible ; inside'

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
  • Amazing thanks! Best answer. Although you need to do text1=${text%";$text2"} to remove the trailing ; in $1text – pez Mar 17 '20 at 19:38

In addition to the other solutions, you could try something regex based:

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

or depending on what you are trying to do exactly, you could use

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

where \1 and \2 contain the two substrings you were wanting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.