how to iterate though delimited values in bash

后端 未结 3 1969
攒了一身酷
攒了一身酷 2021-01-28 17:41

BASH

input: cat test

  1 a;b;c;d
  2 a;b;c;d
  3 a;b;c;d

desired output is:

  1 a
  1 b
  1 c
  1 d
  2 a
  2 b
  2 c
          


        
3条回答
  •  悲哀的现实
    2021-01-28 18:15

    Straightforward shell:

    IFS=" ;"
    shopt noglob # or set -f
    while read -r line; do 
      set -- $line; a=$1; shift
      for b; do printf '%s %s\n' "$a" "$b"; done
    done
    # if data never contains backslash can omit -r from read
    # if data never contains glob patterns (? * [..] etc) can omit set -f
    # if data never contains backslash and first col never begins with hyphen
    # can replace printf with echo "$a" "$b" 
    

    Clever shell, if first column never contains percent or backslash:

    IFS=" ;"
    shopt noglob # or set -f
    while read -r line; do 
      set -- $line; a=$1; shift
      printf "$a %s\n" "$@"
    done
    # read -r and set -f as above
    

    Both of these leave IFS and (maybe) noglob changed; if this is all or the last part of a script, or a function using (), those changes are to a local instance and discarded. Otherwise either explicitly save and restore, or surround with () so they are discarded.

    Similarly both clobber the positional arguments, which generally matters only when in a script or function; if those are needed subsequently, save and restore them, or alternatively in bash or ksh only use a separate explicit array variable:

    IFS=" ;"
    shopt noglob # or set -f
    while read -ra ary; do
      a=${ary[0]}; unset ary[0]
      for b in "${ary[@]}"; do printf '%s %s\n' "$a" "$b"; done
      # or 
      printf "$a %s\n" "${ary[@]}"
    done
    

提交回复
热议问题