Find the answer to your Linux question:
Results 1 to 6 of 6
The read command in bash allows one line worth of input from a user and allows me to set that input as a variable as soon as they hit enter. ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Feb 2006
    Posts
    2

    Bash - Multi-line read


    The read command in bash allows one line worth of input from a user and allows me to set that input as a variable as soon as they hit enter.
    What I want to do is allow read input until an escape charachter (that I define) is typed (preferably on a line by itself).
    The point of this is to accept a whole essay worth of input strore it as a variable and use it in other functions.

    I am really new to bash scripting and could really use some help.
    Thanks ahead of time.

  2. #2
    Linux Guru lakerdonald's Avatar
    Join Date
    Jun 2004
    Location
    St. Petersburg, FL
    Posts
    5,035
    You could always run something like this from a script:
    Code:
    cat > /tmp/foo.txt
    input=`cat /tmp/foo.txt`
    And just have the user input ^D when they're done typing.

  3. #3
    Linux Enthusiast scientica's Avatar
    Join Date
    Sep 2003
    Location
    South- or "Mid-" Sweden
    Posts
    742
    I think you can use read for this too, deep down (almost hidden) in the manual there's this documentation:
    Code:
           read  [-ers]  [-u  fd]  [-t  timeout] [-a aname] [-p prompt] [-n nchars] [-d
           delim] [name ...]
                  One line is read from the standard input, or from the file descriptor
                  fd supplied as an argument to the -u option, and the  first  word  is
                  assigned  to  the first name, the second word to the second name, and
                  so on, with leftover words and their intervening separators  assigned
                  to  the  last  name.   If  there  are fewer words read from the input
                  stream than names, the remaining names  are  assigned  empty  values.
                  The  characters  in  IFS  are used to split the line into words.  The
                  backslash character (\) may be used to remove any special meaning for
                  the  next character read and for line continuation.  Options, if sup-
                  plied, have the following meanings:
                  -a aname
                         The words are assigned to  sequential  indices  of  the  array
                         variable  aname, starting at 0.  aname is unset before any new
                         values are assigned.  Other name arguments are ignored.
                  -d delim
                         The first character of delim is used to  terminate  the  input
                         line, rather than newline.
                  -e     If the standard input is coming from a terminal, readline (see
                         READLINE above) is used to obtain the line.
                  -n nchars
                         read returns after reading nchars characters rather than wait-
                         ing for a complete line of input.
                  -p prompt
                         Display  prompt on standard error, without a trailing newline,
                         before attempting to read any input.  The prompt is  displayed
                         only if input is coming from a terminal.
                  -r     Backslash  does not act as an escape character.  The backslash
                         is considered to be part of the line.  In particular, a  back-
                         slash-newline pair may not be used as a line continuation.
                  -s     Silent  mode.   If input is coming from a terminal, characters
                         are not echoed.
                  -t timeout
                         Cause read to time out and return failure if a  complete  line
                         of  input is not read within timeout seconds.  This option has
                         no effect if read is not reading input from the terminal or  a
                         pipe.
                  -u fd  Read input from file descriptor fd.
    
                  If  no  names are supplied, the line read is assigned to the variable
                  REPLY.  The return code is zero, unless end-of-file  is  encountered,
                  read  times  out,  or  an  invalid file descriptor is supplied as the
                  argument to -u.
    my interprentation is that "one line" is all text untill the 'delim', which you can set by "-d delim", thus:
    read -d `echo -e "\e"` -p "Enter something (end with ESC): "
    should work, a quick test seems to suggest that newlines are 'translated' to spaces - I'll leave the testing up to you (unless lakerdonlad's solution with cat does the trick for you )
    Regards Scienitca (registered user #335819 - http://counter.li.org )
    --
    A master is nothing more than a student who knows something of which he can teach to other students.

  4. #4
    Just Joined!
    Join Date
    Feb 2006
    Posts
    2

    Woot.

    Thanks a bunch.
    Both solutions work and I am a very happy man.
    so stinking simple it's annoying .

    Saving to a file though slightly inelegant works great and is nice and simple, my only concern is the rare system where I won't have write privledges, but saving to the home folder and deleting it when I am done should work well. Got a question though, how do I use that like I would a variable? I know I can just cat /tmp/foo.txt and my lovely text pops on the screen but using it as part of a function is a little different. . .
    I tired simply typing:
    testing=cat /tmp/foo.txt
    which though I expected to error out and yell at me about my syntax, told me "permission denied" this led me to believe I somehow stumbled on to the right path, so I did a chmod 777 on the file and tried again only to see the words "text file busy" appear in my console. Now thats something I never expected to see in linux, now I wouldn't be surprised to learn that my syntax is horribly wrong and that I can't assign a command and argument to a varaible like that, I would have expected a more sensical error message, why the heck is the "text file busy."

    The second solution is great, and on my sytem at least the newlines are not replaced by spaces but are kept as newlines which is what I want . But for some reason ^] is added to the end of the text while a space is added to the front (I guess that shouldn't be too difficult to remove). My biggest annoyance with this method though is that backspace doesn't work it just gives me a ^?.

    Thanks again for the advice both solutions seem great I am just terribly new at this and would love some help applying them.
    i.e. getting the text file into a nice usable variable or getting a more user friendly read.

  5. #5
    Linux Enthusiast scientica's Avatar
    Join Date
    Sep 2003
    Location
    South- or "Mid-" Sweden
    Posts
    742
    Quote Originally Posted by gurneyhalleck
    Thanks a bunch.
    Both solutions work and I am a very happy man.
    so stinking simple it's annoying .
    heh "everything is easy once you know how to do it"
    Quote Originally Posted by gurneyhalleck
    Saving to a file though slightly inelegant works great and is nice and simple, my only concern is the rare system where I won't have write privledges, but saving to the home folder and deleting it when I am done should work well. Got a question though, how do I use that like I would a variable? I know I can just cat /tmp/foo.txt and my lovely text pops on the screen but using it as part of a function is a little different. . .
    I tired simply typing:
    testing=cat /tmp/foo.txt
    which though I expected to error out and yell at me about my syntax, told me "permission denied" this led me to believe I somehow stumbled on to the right path, so I did a chmod 777 on the file and tried again only to see the words "text file busy" appear in my console. Now thats something I never expected to see in linux, now I wouldn't be surprised to learn that my syntax is horribly wrong and that I can't assign a command and argument to a varaible like that, I would have expected a more sensical error message, why the heck is the "text file busy."
    I've never seen that ("text filem busy") error messge, but first, if you want a temporary file you should use mktemp ("man mktemp", also includes a few nice examples).
    also
    Code:
    testing=cat /tmp/foo.txt
    would set the variable to "cat" and then try to execute /tmp/foo.txt - and unless it's executable it'll give and error. what you want is to do this:
    Code:
    testing=`cat /tmp/foo.txt`
    which will set testing to the "stdout from the command 'cat /tmp/foo.txt'" (read: the contents of /tmp/foo.txt)

    Quote Originally Posted by gurneyhalleck
    The second solution is great, and on my sytem at least the newlines are not replaced by spaces but are kept as newlines which is what I want . But for some reason ^] is added to the end of the text while a space is added to the front (I guess that shouldn't be too difficult to remove). My biggest annoyance with this method though is that backspace doesn't work it just gives me a ^?.
    ^[ is the shells way of showing an "escape" char, and I think ^? would be backspace. (other common are ^C = Ctrl-C, ^D = Ctrl-D, ^M = CR(Carrige Return, if you open an DOS file you might see these at the end of the lines, since DOS uses CRLF (Carrige Return + Line Feed) for new lines where as *nix use just LF) ) You could prevent read from echoing the output, but then you wouldn't see any of the chars you type. For the time beeing I can't see any simple solution, one way could be to make it more complex, something like:
    Code:
    # pseudo bash (untested):
    MyCoolVariable=""
    read -n 1 -a CHAR -s
    while [ "x$CHAR" != "x`echo -e "\e"`" ] ; do
      echo $CHAR
      MyCoolVariable="$MyCoolVariable$CHAR"
      read -n 1 -a CHAR -s
    done
    echo "Whole input was: $MyCoolVariable"
    Regards Scienitca (registered user #335819 - http://counter.li.org )
    --
    A master is nothing more than a student who knows something of which he can teach to other students.

  6. #6
    Linux User muha's Avatar
    Join Date
    Jan 2006
    Posts
    290
    Quote Originally Posted by gurneyhalleck
    Got a question though, how do I use that like I would a variable?
    what i do (newbie code here but it works ..) is sourcing the inputfile:
    When a file is sourced (by typing either source filename or . filename at the command line), the lines of code in the file are executed as if they were printed at the command line.
    contents of getvar.sh:
    Code:
    #!/bin/bash
    
    #	-------------------------------------------------------------------
    #
    #	Shell program to read variables from a textfile
    #
    #	Usage:
    #		save as getvar.sh
    #		chmod +x getvar.sh
    #		use as ./getvar.sh -f ./input.txt > ./outputfile.txt
    #
    
    #	-------------------------------------------------------------------
    #	Variables
    #	-------------------------------------------------------------------
    	
    	# set the standard input-file; overwritten by -f <another inputfile>
    	filename=
    
    #	-------------------------------------------------------------------
    #	Functions
    #	-------------------------------------------------------------------
    
    
    function test_if_file_exist
    {
    
    #	-----------------------------------------------------------------------
    #	Function to test if a file exists
    #		No arguments
    #	-----------------------------------------------------------------------
    
    	if [ "$filename" != "" ]; then
    		if [ -f $filename ]; then
    			if ! [ -w $filename ]; then
    				echo "Input file is not writable"
    				exit
    			fi
    		else
    			echo "Output file does not exist or is not a regular file"
    			exit
    		fi
    	fi
    }
    
    
    function get_variables_from_file
    {
    
    #	-----------------------------------------------------------------------
    #	Function to get variables from an input-file named $filename
    #		No arguments
    #	-----------------------------------------------------------------------
    
    	# get variables from $filename by sourcing it
    		. $filename
    }
    
    
    #	-------------------------------------------------------------------
    #	Program starts here
    #	-------------------------------------------------------------------
    
    ##### Command Line Processing #####
    
    while [ "$1" != "" ]; do
        case $1 in
            -f | --file )           shift
    				if [ "$1" != "" ]; then
    					filename=$1
    				else
    					exit 1
    				fi
    				;;
            * )                     exit 1
        esac
        shift
    done
    
    ##### File usage #####
    test_if_file_exist
    
    ##### Main Logic #####
    
    # start by sourcing the $filename file 
    get_variables_from_file
    
    # Output some text
    cat <<- _EOF_
    output some text.
    
    _EOF_
    
    # output a variable
    	echo $footer_home
    	echo $filename
    
    exit
    contents of a inputfile called input.txt:
    Code:
    # this is the input.txt file
    # specify a variable
    footer_home="The file where i just got a variable from was:"
    the eventual output looks like:
    Code:
    output some text.
    
    The file where i just got a variable from was:
    ./input.txt
    Does that work for you?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •