HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Input Columns with Awk

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
inputawkwithcolumns

Problem

I wrote a small script to manipulate fields of a file based on the input of a user. Is there something I could've done better, or perhaps a better refactor? I do know however that I need a way to validate for empty fields.

view_column() {
  for i in "$file_name"; do
    cat "$i" | awk -v col="$1" '{ print $col }'
  done
}

print_menu() {
  menu=( 'First' 'Last' 'Email' 'Exit' )
  for (( i=0; i<${#menu[@]}; i++ )); do
    printf "%2d. %s\n" "$((i+1))" "${menu[$i]}"
  done
}

main() {
  while true; do 
    clear
    print_menu
    read -p 'Enter a choice: ' choice
    if (( "$choice" == 4 )); then
      break
    fi
    view_column "$choice"
    sleep 1.5
  done
}

Solution

That's very elegant looking code. bash has a builtin select statement to present a menu to the user and get a response --
the advantage of select is that the user is locked into it until a valid response is obtained. Plus, it seems that printing the menu and reading the response should be together.

My code below is not as beautiful as yours, but it allows you to localize all knowledge about the file structure into a single line: local fields=(...)

main() {
  local PS3='Enter a choice: '
  local fields=(First Last Email)

  # reverse the fields array: map field names to column numbers
  local -A column
  for (( i=0; i < ${#fields[@]}; i++)); do
    column[${fields[i]}]=$((i+1))
  done

  while true; do
    clear
    select choice in "${fields[@]}" Exit; do
      # invalid response
      [[ -z $choice ]] && continue

      # exit
      [[ $choice = "Exit" ]] && return

      # do something interesting
      view_column "${column[$choice]}"
      sleep 1.5
      break
    done
  done
}

Code Snippets

main() {
  local PS3='Enter a choice: '
  local fields=(First Last Email)

  # reverse the fields array: map field names to column numbers
  local -A column
  for (( i=0; i < ${#fields[@]}; i++)); do
    column[${fields[i]}]=$((i+1))
  done

  while true; do
    clear
    select choice in "${fields[@]}" Exit; do
      # invalid response
      [[ -z $choice ]] && continue

      # exit
      [[ $choice = "Exit" ]] && return

      # do something interesting
      view_column "${column[$choice]}"
      sleep 1.5
      break
    done
  done
}

Context

StackExchange Code Review Q#28880, answer score: 2

Revisions (0)

No revisions yet.