1

The following example is taken from William Shott's The Linux command line. It is a shell script which gathers user info from the /etc/passwd file. The specific user for which this is done is read from stdin.

My question is about the "here string" used in line 7. Just for kicks, I tried using the redirection operator instead, but it did not work. Why?

PS: I have some background in C++ so I expected the string file_info to act as a stringstream.

     1  #!/bin/bash

     2  # read-ifs: read fields from a file

     3  FILE=/etc/passwd

     4  read -p "Enter a username > " user_name

     5  file_info="$(grep "^$user_name:" $FILE)"

     6  if [ -n "$file_info" ]; then
     7       IFS=":" read user pw uid gid name home shell <<< "$file_info"
     8       echo "User = '$user'"
     9       echo "UID = '$uid'"
    10       echo "GID = '$gid'"
    11       echo "Full Name = '$name'"
    12       echo "Home Dir. = '$home'"
    13       echo "Shell = '$shell'"

    14  else
    15      echo "No such user '$user_name'" >&2
    16      exit 1
    17  fi

  • What exactly did you try? The operators >,>>,< work on streams not variables, however you could use a process substitution to stream the contents of the variable ex. IFS=":" read user pw uid gid name home shell < <(printf '%s' "$file_info") – steeldriver Dec 20 '19 at 03:07
  • @steeldriver this is kind of the answer I was looking for. Can you elaborate though on this: < <(printf '%s' "$file_info") – An Ignorant Wanderer Dec 20 '19 at 03:28
  • Highly relevant https://askubuntu.com/q/678915/295286 There's also explanation of how herestrings work and how they are implemented at C level – Sergiy Kolodyazhnyy Jan 02 '20 at 08:34

1 Answers1

0

If you do something like

grep "^$user_name:" $FILE | IFS=":" read user pw uid gid name home shell
echo "User = '$user'"

the right side of the pipeline (the read command) is run in its own subshell process and the variables it sets are gone when it ends so echo just displays empty strings.

But you can do something like

grep "^$user_name:" $FILE | ( IFS=":" read user pw uid gid name home shell
    echo "User = '$user'" )

In this case the whole ( ... ) part is run in the same subshell and the variables are available for the echo call.