grep vs do while read

I have inherited the UNIX scripting duties for our team and have only been at this for a few months so I apologize for what may be a simple question.

We have a script we are reworking. Part of this script takes a parameter and reads a csv file. When it finds a matching line, the cut command is used to parse out and assign script variables from the matching line.

This works fine (code shown below). My question is really just a general one. I get the idea of using grep to "filter" just the records we want (based on $1, and then again, the lines that end with 'C')

In our case the file is very small no more than 25 lines. I am wondering if we could also use a do while read loop to actually "read" the file line by line instead of using grep - what would be the merits of each approach?

Any input you have would be greatly appreciated!

thanks,

JH

set RECORDS = `grep ^$1 ${CFGFILE} | grep 'C$'`

foreach record ( ${RECORDS} )
set rSID = `echo $record | tr -s " " | cut -f1 -d","`
set rCLIENT = `echo $record | tr -s " " | cut f2 -d","'
set rINSTANCE = `echo $record | tr -s " " | cut -f3 -d","`
set rSERVER = `echo $record | tr -s " " | cut -f4 -d","`
set rTYPE = `echo $record | tr -s " " | cut -f5 -d","`

I have inherited the UNIX scripting duties on our team and have only been at this for few months. I apologize for what may be a basic question.

We have this snippet of code that gets lines from a file (using grep) based on a parameter we pass in (code shown below).

My question about this is that this code works when we execute it in a c-shell (#!/bin/csh) but not in bourne shell (#!/bin/sh).

I was wondering if there is a syntactical difference for this, and / or if there would be bourne shell equivalent.

Every script we have runs bourne shell, so I am wondering if there is any potential problems running this one as c-shell; better put, I'd be reluctant to run it as c-shell just for the sake of keeping this code.

Any info or direction would be greatly appreciated,

thanks

JH

set RECORDS = `grep ^$1 ${CFGFILE} | grep 'C$'`
foreach record ( ${RECORDS} )
set rSID = `echo $record | tr -s " " | cut -f1 -d","`
set rCLIENT = `echo $record | tr -s " " | cut f2 -d","'
set rINSTANCE = `echo $record | tr -s " " | cut -f3 -d","`
set rSERVER = `echo $record | tr -s " " | cut -f4 -d","`
set rTYPE = `echo $record | tr -s " " | cut -f5 -d","`

Yes, csh is very different from sh, and you're doing well to avoid it.

RECORDS = `grep ^$1 ${CFGFILE} | grep 'C$'`
for record in ${RECORDS}
do
        rSID = `echo $record | tr -s " " | cut -f1 -d","`
        rCLIENT = `echo $record | tr -s " " | cut f2 -d","'
        rINSTANCE = `echo $record | tr -s " " | cut -f3 -d","`
        rSERVER = `echo $record | tr -s " " | cut -f4 -d","`
        rTYPE = `echo $record | tr -s " " | cut -f5 -d","` 
done

This is just a direct transliteration, as inelegant as it started as. There's probably a better way, avoiding the creation of 15 superfluous processes if we knew exactly what this script did.

reading in a loop would allow you to process an arbitrary number of records without worrying about the maximum size of variable your shell allows. Note my code is in sh, not csh:

grep ^$1 ${CFGFILE} | grep 'C$' | while read RECORD
do
...
done

Those two grep processes could probably be combined into one if you used egrep instead:

egrep "^$1.*C$" | while read RECORD
do
...
done

But these pipes do something potentially unexpected, insulating themselves from variables outside the loop:

VAR=s

echo 'a b c ' | while read -d ' ' Q
do
        echo $Q
        VAR=$Q
done

echo "VAR is $VAR"

Because the loop behind the pipe is a seperate process, variable changes in it are not reflected outside it, hence VAR remains S.

sh's built-in string splitting ability makes a lot of that csh code redundant, in fact, I wonder if this works properly with your data:

IFS=","
egrep "^$1.*C$" | tr -s ' ' | while read rSID rCLIENT rINSTANCE rSERVER rTYPE
do
        echo "rSID = $rSID"
        echo "rCLIENT = $rCLIENT"
        echo "rINSTANCE = $rINSTANCE"
        echo "rSERVER = $rSERVER"
        echo "rTYPE = $rTYPE"
done