Iman
Iman

Reputation: 414

Bash - read Postgresql zero separated fields into array

I want to read the output of a psql query produced with --field-separator-zero into an array inside my bash script. The best I have tried was the following:

psql -w  -t --quiet --no-align --field-separator-zero -c $'select nickname,first_name,last_name,email from users' | while IFS= read -d '' -a USERS; do 
     echo ${USERS[0]} ${USERS[1]} ${USERS[2]} ${USERS[3]}; 
done;

The above would return each field of a row as a new array. Changing the delimiter to anything else would make the process work, but the problem is the nickname field might contain any character, so I'm forced to use the safe NUL char as a delimiter. Is there any way to do this ?

Upvotes: 0

Views: 806

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295716

I'm assuming here that nickname is a unique key; make the appropriate modifications if a different field should be used in that role.

The below code reads the data into a series of associative arrays, and emits each row in turn.

Note that associative arrays are a Bash 4 feature; if you're on Mac OS, which ships 3.2, use MacPorts or a similar tool to install a modern release.

declare -A first_names=( ) last_names=( ) emails=( )
while IFS= read -r -d '' nickname && \
      IFS= read -r -d '' first_name && \
      IFS= read -r -d '' last_name && \
      IFS= read -r -d '' email; do
  first_names[$nickname]=$first_name
  last_names[$nickname]=$last_name
  emails[$nickname]=$email
done < <(psql ...)

echo "Found users: "
for nickname in "${!emails[@]}"; do
  printf 'nickname - %q\n' "$nickname"
  printf 'email - %q\n' "${emails[$nickname]}"
  printf 'first name - %q\n' "${first_names[$nickname]}"
  printf 'last name - %q\n' "${last_names[$nickname]}"
  echo
done

This technique is described in BashFAQ #1 -- search for -print0 to find its mention.

Upvotes: 2

Related Questions