1

I am making a bash script. I have to get 3 variables

VAR1=$(cat /path to my file/ | grep "string1" | awk '{ print $2 }'
VAR2=$(cat /path to my file/ | grep "string2" | awk '{ print $2 }'
VAR3=$(cat /path to my file/ | grep "string3" | awk '{ print $4 }'

My problem is that if I write

echo $VAR1
echo $VAR2
echo $VAR3

I can see values correctly

But when I try to write them in one line like this

echo "VAR1: $VAR1 VAR2: $VAR2 VAR3: $VAR3"

Value from $VAR3 is written at the beginning of output overwritting values of $VAR1 and $VAR2

I expect my explanation had been clear. Any doubt please let me know

Thanks and regards.

Rambert

3
  • 3
    cat /path to my file/ | grep "string1" | awk '{ print $2 }' == awk '/string1/{print $2}' file. No need for cat or grep with awk. Commented Jun 29, 2016 at 12:01
  • @andlrc : echo will not interpret \r then without -e Commented Jun 29, 2016 at 12:14
  • One thing. All variables are strings of numbers. Commented Jun 29, 2016 at 12:16

2 Answers 2

5

It seems to me that $VAR3 contains \r which in some shells will move the cursor to the beginning of the line. Use printf instead:

printf "VAR1: %s VAR2: %s VAR3: %s\n" "$VAR1" "$VAR2" "$VAR3"

Also note that the way you extract the values is highly inefficient and can be reduced to one call to awk:

read -r var1 var2 var3 _ < <(awk '/string1/ { a=$2 }
                                  /string2/ { b=$2 }
                                  /string3/ { c=$4 }
                                        END { print(a, b, c) }' /path/to/file)
printf "VAR1: %s VAR2: %s VAR3: %s\n" "$var1" "$var2" "$var3"

A nitpick is that uppercase variable names are reserved for environment variables, so I changed all to lowercase.

<(...) is a process substitution and will make ... write to a "file" and return the file name:

$ echo <(ls)
/dev/fd/63

And command < file is a redirection changing standard input of command to be comming from the file file.

Sign up to request clarification or add additional context in comments.

3 Comments

Now that I think of it, read -r a b c <<< "1 2 3" will not work when one value is missing: read -r a b c <<< "1 3" Note that two spaces will be squeezed together and 3 will be stored in b. One could however find another delimiter than space and use IFS accordingly: IFS=: read -r a b c <<< "1::3". Now 3 will be stored in c. (Even SO will squeeze the spaces, but it is: <<< "1<space><space>3")
You are right. I have edited file with notepad++ and i have seen \r on all lines. So if i convert lines file to Unix everything is OK. I get file from ftp in txt format so i have to convert it and work with it
@RambertNala There is a million ways to convert line endings :-) See How to convert DOS/Windows newline (CRLF) to Unix newline (\n) in bash script?
1

You could write :

cat /path to my file/ | grep "string1" | awk '{ print $2 }'

as

awk '/string1/{print $2}' /path/to/file

In other words you could do with awk alone what you intended to do with cat, grep & awk

So finally get :

VAR1=$(awk '/string1/{print $2}' /path/to/file) #mind the closing ')'

Regarding the issue you face, it looks like you have carriage returns or \r in your variables. In bash echo will not interpret escape sequences without the -e option, but the printf option which
[ @andlrc ] pointed out is a good try though as he mentioned in his [ answer ]

which in some shells will move the cursor to the beginning

Notes :

  1. Another subtle point to keep in mind is to avoid using upper case variable names like VAR1 for user scripts. So replace it with var1 or so
  2. When assigning values to variable spaces are not allowed around =, so

    VAR1="Note there are no spaces around = sign"
    

    is the right usage

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.