How do I split a string on a delimiter in Bash?

后端 未结 30 2006
萌比男神i
萌比男神i 2020-11-21 04:58

I have this string stored in a variable:

IN=\"bla@some.com;john@home.com\"

Now I would like to split the strings by ; delimite

相关标签:
30条回答
  • 2020-11-21 05:43

    In Android shell, most of the proposed methods just do not work:

    $ IFS=':' read -ra ADDR <<<"$PATH"                             
    /system/bin/sh: can't create temporary file /sqlite_stmt_journals/mksh.EbNoR10629: No such file or directory
    

    What does work is:

    $ for i in ${PATH//:/ }; do echo $i; done
    /sbin
    /vendor/bin
    /system/sbin
    /system/bin
    /system/xbin
    

    where // means global replacement.

    0 讨论(0)
  • 2020-11-21 05:44

    I think AWK is the best and efficient command to resolve your problem. AWK is included by default in almost every Linux distribution.

    echo "bla@some.com;john@home.com" | awk -F';' '{print $1,$2}'
    

    will give

    bla@some.com john@home.com
    

    Of course your can store each email address by redefining the awk print field.

    0 讨论(0)
  • 2020-11-21 05:45

    Apart from the fantastic answers that were already provided, if it is just a matter of printing out the data you may consider using awk:

    awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
    

    This sets the field separator to ;, so that it can loop through the fields with a for loop and print accordingly.

    Test

    $ IN="bla@some.com;john@home.com"
    $ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
    > [bla@some.com]
    > [john@home.com]
    

    With another input:

    $ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;c   d;e_;f"
    > [a]
    > [b]
    > [c   d]
    > [e_]
    > [f]
    
    0 讨论(0)
  • 2020-11-21 05:46

    Two bourne-ish alternatives where neither require bash arrays:

    Case 1: Keep it nice and simple: Use a NewLine as the Record-Separator... eg.

    IN="bla@some.com
    john@home.com"
    
    while read i; do
      # process "$i" ... eg.
        echo "[email:$i]"
    done <<< "$IN"
    

    Note: in this first case no sub-process is forked to assist with list manipulation.

    Idea: Maybe it is worth using NL extensively internally, and only converting to a different RS when generating the final result externally.

    Case 2: Using a ";" as a record separator... eg.

    NL="
    " IRS=";" ORS=";"
    
    conv_IRS() {
      exec tr "$1" "$NL"
    }
    
    conv_ORS() {
      exec tr "$NL" "$1"
    }
    
    IN="bla@some.com;john@home.com"
    IN="$(conv_IRS ";" <<< "$IN")"
    
    while read i; do
      # process "$i" ... eg.
        echo -n "[email:$i]$ORS"
    done <<< "$IN"
    

    In both cases a sub-list can be composed within the loop is persistent after the loop has completed. This is useful when manipulating lists in memory, instead storing lists in files. {p.s. keep calm and carry on B-) }

    0 讨论(0)
  • 2020-11-21 05:47

    Without setting the IFS

    If you just have one colon you can do that:

    a="foo:bar"
    b=${a%:*}
    c=${a##*:}
    

    you will get:

    b = foo
    c = bar
    
    0 讨论(0)
  • 2020-11-21 05:48

    This also works:

    IN="bla@some.com;john@home.com"
    echo ADD1=`echo $IN | cut -d \; -f 1`
    echo ADD2=`echo $IN | cut -d \; -f 2`
    

    Be careful, this solution is not always correct. In case you pass "bla@some.com" only, it will assign it to both ADD1 and ADD2.

    0 讨论(0)
提交回复
热议问题