Bash split string on delimiter, assign segments to array

后端 未结 3 1238
野趣味
野趣味 2020-12-31 09:28

In bash, I would like to transform a PATH-like environment variable that may contain space-separated elements into an array, making sure eleme

3条回答
  •  长发绾君心
    2020-12-31 10:06

    f() {
      local IFS=:
      local foo
      set -f # Disable glob expansion
      foo=( $@ ) # Deliberately unquoted 
      set +f
      printf '%d\n' "${#foo[@]}"
      printf '%s\n' "${foo[@]}"
    }
    
    f 'un:dodecaedro:per:tirare:per:i danni'
    6
    un
    dodecaedro
    per
    tirare
    per
    i danni
    

    Modifying Jim McNamara's answer, you could just reset IFS:

    oIFS="$IFS"
    foo='un:dodecaedro:per:tirare:per:i danni'
    IFS=: arr=( $foo )
    IFS="$oIFS"
    

    I prefer the function scope because it protects IFS changes from bleeding into the global scope without requiring special care to reset it.

    Edits and explanations:

    As a matter of clarification: In the second example, the IFS setting does change the global variable. The salient difference between this:

    IFS=: arr=( $foo )
    

    and this:

    IFS=: read -a arr <<< "$foo"
    

    is that the former is two variable assignments and no commands, and the latter is a simple command (see simple command in man (1) bash.)

    Demonstration:

    $ echo "$BASH_VERSION"
    3.2.48(1)-release
    $ echo "$IFS"
    
    
    $ foo='un:dodecaedro:per:tirare:per:i danni'
    $ IFS=: read -a arr <<< "$foo"
    $ echo "${#arr[@]}"
    6
    $ echo "$IFS"
    
    
    $ IFS=: arr1=( $foo )
    $ echo "${#arr1[@]}"
    6
    $ echo "$IFS"
    :
    

提交回复
热议问题