Tremors
Tremors

Reputation: 133

How to use contents of text file as input to shell script?

I'm tasked with writing a shell script that takes in a string of 6 letters and numbers and checks if they meet a certain criteria.

This is that script

FILE=$1
var=${#FILE}
if [ $var -gt 6 ] || [ $var -lt 6 ]
then
    #echo $FILE "is not a valid NSID"
    exit 1
else if ( echo $1 | egrep -q '^[A-Za-z]{3}\d{3}$' )
    then
        #echo $1 "is a valid NSID"
        exit 0
    else
        #echo $1 "is not a valid NSID"
        exit 1
    fi
fi

It works. so that isn't where the problem is.

What I am trying to do is use a "wrapper" script to gather potential valid NSID's from a text file and call that script on the list of inputs. so that if I call that script within my wrapper script it will step through the text file I have given my wrapper and check if each line is valid.

FILE=$1
YES= more $FILE

if ( exec /path/to/file/is_nsid.sh $YES -eq 0 )
then
    echo $FILE "is a valid NSID"
else
    echo $FILE "is not a valid NSID"
fi

so if I called it with a text file called file1.txt which contained

yes123
yess12
ye1243

it would output whether each was valid or not.

Upvotes: 1

Views: 2142

Answers (1)

rici
rici

Reputation: 241671

The line

YES= more $FILE

Sets YES in the environment passed to the command more $FILE. That's probably not what you intended.

The line

if ( exec /path/to/file/is_nsid.sh $YES -eq 0 )

starts a subshell to execute exec /path/to/file/is_nsid.sh $YES -eq 0. (That's what the parentheses do.) exec then replaces the subshell with a process which executes

/path/to/file/is_nsid.sh $YES -eq 0

which in turn runs the script at is_nsid.sh, passing it two or three command line arguments:

  • the value of $YES. This could be several arguments if the value of the shell variable includes whitespace or a glob symbol, but in this case it is more likely to be nothing since $YES has not been defined.

  • -eq

  • 0

Since your script only examines its first argument, that's probably equivalent to

/path/to/file/is_nsid.sh -eq

That will, presumably, terminate with a failure status code, and since the subshell has been replaced with the script execution, that will also be the return status of the subshell. (Without exec, there would be essentially no difference; the subshell's return status is that of the last command executed in the subshell. Without either the parentheses or the exec, the result would also be the same. So you could have just written if /path/to/file/is_nsid.sh $YES -eq 0 and it would produce the same incorrect result.)

What you presumably wanted to do was to read each line in the file whose name is passed as the first command-line argument to the script. You could do that as follows:

while read -r line; do
  if /path/to/file/is_nsid.sh "$line"; then
    echo "$line is a valid NSID"
  else
    echo "$line is not a valid NSID"
  fi
done < "$1"

You could simplify your is_nsid script considerably. The following is equivalent:

[ $#1 -eq 6 ] && echo "$1" | egrep -q '^[A-Za-z]{3}\d{3}$'

Note that \d is a Gnu extension to egrep and should not be relied on in portable code (which I assume this is trying to be). You should use [0-9] or [[:digit:]] instead.

The length check is actually unnecessary since the regex can only match six-character lines. Personally, I'd leave it out and just use

echo "$1" | egrep -q '^[[:alpha:]]{3}[[:digit:]]{3}$'

I removed all the unnecessary if statements. If I had left them in, I would have changed else if ... then ... fi to simply elif ... then ... to avoid unnecessary if nesting.

Upvotes: 2

Related Questions