Reading a line from an input file.

Reading a line from an input file.

Post by Rob Bradfor » Fri, 02 Dec 2005 05:57:17



Hi.

Can some one please tell me what I am doing wrong, It's probably so
stupid, but I can't see it.  I need to read in some parameters from a
single line in a file based on an input parameter.  A simple test file
amd associated parameter file is given below.  When I run this I for
portugal I get:

$ ./test.sh Pt
Pt Portugal Lisbon Portugese
End

What I would really like to se is;

$ ./test.sh Pt
Pt Portugal Lisbon Portugese
End Pt Portugal Lisbon Portugese

Why are the parameters set inside the loop but not outside, yes It's a
matter of scope but how do I make them available beyond the "done" line?

Any help would be appreciated.

Rob.B

Parameter File test.parm

El Greece Athens Greek
Es Spain Madrid Spanish
Fr France Paris French
Pt Portugal Lisbon Portugese
En England London English
Ie Ireland Dublin Gaelic
Nl Netherlands Amsterdam Dutch

Script test.sh

#! /bin/sh

cat ${0%.*}.parm |
while read CCODE COUNTRY CAPITAL LANG
do
  if [ ${1} = ${CCODE} ]
    then
      echo $CCODE $COUNTRY $CAPITAL $LANG
      break
  fi
done

echo "End"  $CCODE $COUNTRY $CAPITAL $LANG

--

 
 
 

Reading a line from an input file.

Post by Lars Kellogg-Stedma » Fri, 02 Dec 2005 06:30:48



Quote:> Why are the parameters set inside the loop but not outside, yes It's a
> matter of scope but how do I make them available beyond the "done" line?

It's not strictly a matter of scope, at least, not as you would
understand "scope" in the context of most languages.  When you pipe
input into a while loop (as you are doing in this script), the loop is
run *in a subshell*.  This means that any variables set within the loop
will not be available when the loop exits.

There are several ways to work around this problem.

(1) Put the whole script in a subshell:

  (
    while read CCODE COUNTRY CAPITAL LANG
    do
      if [ ${1} = ${CCODE} ]
        then
          echo $CCODE $COUNTRY $CAPITAL $LANG
          break
      fi
    done

    echo "End"  $CCODE $COUNTRY $CAPITAL $LANG
  ) < ${0%.*}.parm

Now your 'while' loop nd the terminal 'echo' statement are executing
at the same shell level.  Also note that you don't need to use 'cat'
to redirect input into the while loop; you can just use the built-in
'<' redirection operator.

(2) Inside the loop, dump variables to a file and then source in that
file after the loop exits:

  while read CCODE COUNTRY CAPITAL LANG
  do
    if [ ${1} = ${CCODE} ]
      then
        echo $CCODE $COUNTRY $CAPITAL $LANG
        cat > vars <<EOF
  CCODE="$CCODE"
  COUNTRY="$COUNTRY"
  CAPITAL="$CAPITAL"
  LANG="$LANG"
  EOF
        break
    fi
  done < ${0%.*}.parm

  . ./vars
  echo "End"  $CCODE $COUNTRY $CAPITAL $LANG

In a production script, you'd want to make sure you clean up the
'vars' file when the script exits.

-- Lars

--

This email address will expire on 2005-11-23.

 
 
 

Reading a line from an input file.

Post by Rob Bradfor » Fri, 02 Dec 2005 08:44:25


Thanks Lars,

I'll Use Option 2 as the production script is quite large and I don't
want to put it all inside the loop.  At least I now know I wasn't going
mad, plus I've learned something.

Rob.B

--

 
 
 

Reading a line from an input file.

Post by Willia » Sat, 03 Dec 2005 02:18:47



Quote:

> Why are the parameters set inside the loop but not outside, yes It's a
> matter of scope but how do I make them available beyond the "done" line?

> Any help would be appreciated.

When you redirect stdin for the loop you create a subshell and
the variables are lost when you exit. One solution is to use
something other than stdin:

exec 3<inputfile # Open input file as descriptor 3
while read CCODE COUNTRY CAPITAL LANG 0<&3
do
  if [ ${1} = ${CCODE} ]
    then
      echo $CCODE $COUNTRY $CAPITAL $LANG
      break
  fi
done
exec 3<&- # Close 3

That assigns inputfile to description 3, then
gets read to pull data from it. You could put that
in a for loop to step through a list of files as in
your original.

-Wm

 
 
 

Reading a line from an input file.

Post by Enrique Perez-Terro » Sun, 04 Dec 2005 08:01:15





>> Why are the parameters set inside the loop but not outside, yes It's a
>> matter of scope but how do I make them available beyond the "done" line?

>> Any help would be appreciated.

> When you redirect stdin for the loop you create a subshell and

Not quite. When you use a pipe, the components of the pipeline are
run in separate subshells.  This applies to bash ans many other shells,
but not to all. Some shells run the last element of the pipeline
in the parent process.

Quote:> the variables are lost when you exit. One solution is to use
> something other than stdin:

> exec 3<inputfile # Open input file as descriptor 3
> while read CCODE COUNTRY CAPITAL LANG 0<&3
> do
>   if [ ${1} = ${CCODE} ]
>     then
>       echo $CCODE $COUNTRY $CAPITAL $LANG
>       break
>   fi
> done
> exec 3<&- # Close 3

> That assigns inputfile to description 3, then
> gets read to pull data from it. You could put that
> in a for loop to step through a list of files as in
> your original

This also works:

   exec < inputfile
   while read CCODE COUNTRY CAPITAL LANG
   do
    ...
   done

as does this:

   while read CCODE COUNTRY CAPITAL LANG
   do
     ...
   done < inputfile

as does this:

   < inputfile while read CCODE COUNTRY CAPITAL LANG
   do
     ..
   done

But this does not work:

   while read CCODE COUNTRY CAPITAL LANG <inputfile
   do
     ...
   done

because the "read" statement is executed repeatedly, and then the input
file is opened and read from the beginning every time. The other forms
only open the file once.  All forms, also the last one, run in the main
process, as there is no pipe.

The form with "exec < intputfile" may be problematic if you need ot
get at the original standard input. This form avoids that:

   exec 3<&0  < inputfile  # save original standard input in fd 3.
   ....
   exec <&3  #restore the original standard input.

-Enrique

 
 
 

Reading a line from an input file.

Post by Chris F.A. Johnso » Sun, 04 Dec 2005 08:42:50






>>> Why are the parameters set inside the loop but not outside, yes It's a
>>> matter of scope but how do I make them available beyond the "done" line?

>>> Any help would be appreciated.

>> When you redirect stdin for the loop you create a subshell and

> Not quite. When you use a pipe, the components of the pipeline are
> run in separate subshells.

   In some, if not all, Bourne shells, just redirection was enough to
   cause execution in a subshell.

--
   Chris F.A. Johnson, author   |    <http://cfaj.freeshell.org>
   Shell Scripting Recipes:     |  My code in this post, if any,
   A Problem-Solution Approach  |          is released under the
   2005, Apress                 |     GNU General Public Licence

 
 
 

Reading a line from an input file.

Post by Sven Maschec » Sun, 04 Dec 2005 09:24:59



>    In some, if not all, Bourne shells, just redirection was enough to
>    cause execution in a subshell.

Redirection of non-simple commands (for, while, {...;}, ...)
 - in all Bourne shells.
 
 
 

1. reading each line of input without writing to a file

I have a complex command that returns several lines of information,
like this:

Info for this line
info_for_this_line
also_some here
some stuff here too

I need to run another command once for each line of this file, passing
the entire line as an argument.  I'll represent my complex command as
"cmd1", and my second command as "echo" to simplify things somewhat.

This script works:

cmd1 > file1
while read thisline
do
   echo $thisline
done < file1

but I don't want to write the information out to a file.  I tried
this:

while read thisline
do
   echo $thisline
done < `cmd1`

but I get a single long string that consists of each line separated by
^J and a shell error, "cannot open".

I don't think I can use a simple for loop, because the loop seems to
execute once per word instead of once per line.

I'm using ksh on HPUX.  Any help is greatly appreciated.

Thanks!

2. Missing function in libxview?

3. read from stdin while reading line by line a file

4. Diamond Stealth 3D 2000 Pro & signal 11

5. How to read line by line of a file

6. Serial PPP connection between two machines?

7. HELP: How do I read a file line-by-line without getting spaces stripped?

8. mouse TrackMan Vista - X freezes

9. read a file line by line

10. How to read line by line from a file?

11. Read a file line after line

12. reading files line-be-line?

13. Line by line file read