1

I have written a small shell script to get some values from a text file and have them in a for loop to use them as a variables which I will be using as an input to a wsadmin command. Below is the shell script I have written.

FILE=`cat test.txt`

for i in `echo "$FILE"`

do
DS_NAME=`echo "$i"|awk -F"=" '{print $2}'`
HOST_NAME=`echo "$i"|awk -F"=" '{print $2}'`
PORT_NUMBER=`echo "$i"|awk -F"=" '{print $3}'`
DB_NAME=`echo "$i"|awk -F"=" '{print $4}'`

echo "$DS_NAME"

echo "$HOST_NAME"

echo "$PORT_NUMBER"

echo "$DB_NAME"

done

The contents of my test.txt file are below.

test connection data source=test.connect.com=1234=testdb
test connection data source=test1.connect.com=1134=test1db
test connection data source=test2.connect.com=1234=test2db

When I execute the shell script I'm looking for an output like below.

test connection data source
test1.connect.com
1234
testdb

But unfortunately I'm not getting what I needed and I believe its because of the spaces between words in DS_NAME.How can I get around this ? Any suggestions please.

1

FILE=`cat test.txt` stores the content of the file (except for trailing newlines) in the variable FILE. Then echo "$FILE" prints the file content (assuming that it doesn't start with a dash and doesn't contain any backslashes). It would have been simpler to directly write

for i in `cat test.txt`

Next, the command substitution `…` in a context that allows word splitting breaks the output of the command into words, not lines. (This is a default and it can be changed, although that's not the best way to solve your problem.) That's your visible problem: the loop runs once for each word, not once for each line. In addition, the words are treated as shell wildcard pattern: if there's a line like test * source=a=b=c, the * will be replaced by the list of file names in the current directory.

Using awk to extract fields from the line works (apart from the mangling from echo), but it's overly complicated and slow.

There's a shell builtin that reads a line and splits it into fields: read. Just use that. To use the character = as the field delimiter, set the variable IFS for the read command. Pass the option -r to read unless you want to treat a backslash at the end of a line as indicating a continuation line.

while IFS='=' read -r DS_NAME HOST_NAME PORT_NUMBER DB_NAME ignored; do
  …
done <test.txt

The extra variable ignored makes your parser more robust in case there's an extra field, e.g.

test connection data source=test.connect.com=1234=testdb=hey, a new field
1
  • Gilles - Thank you very much. This worked like a charm.Really appreciate it. – avin9999 Sep 3 '20 at 13:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.