Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a file with this structure:


and here is my program:



cat input.txt | while read col1 col2 col3; do
    echo ${col1}
    echo ${col2}
    echo ${col3}
    echo "********************************"

I want to insert ${token} while reading file. because token is a dynamic word and I can not change it inside the file every time. So I add ${token} to the file once. But the output of program is:


Why this is happening? ma${token}jid should be expand like this: echo ma${token}jid, then 12345678 should be inserted.

share|improve this question
up vote 1 down vote accepted

The value of col1 is the 13-character string ma${token}jid. When you write echo ${col1} with no quotes, the shell replaces ${col1} by the value of the variable, then performs word splitting (i.e. breaking up the value into separate words at $IFS characters) and filename generation (i.e. globbing). Variable values are not recursively expanded using shell syntax. If you use double quotes around variable substitution (which you should do unless you have a good reason not to), "$col1" straightforwardly expands to the value of col1.

If your strings are tame enough (i.e. contain no shell special characters, apart from the ${token} that you want to substitute), then you can construct a string from $col1 that you evaluate as a shell snippet. In your example, the following line would print ma12345678jid:

eval "echo $col1"

Alternatively, replace the marker ${token} by the desired value. You can do it with a string substitution in bash:

while read -r col1 col2 col3; do
    echo "${col1//'${token}'/$token}"
    echo "${col2}"
    echo "${col3}"
    echo "********************************"
done <input.txt

You can also do it with awk, as a pre- or post-processing step (depending on whether you want to perform the replacement in other columns as well).

<input.txt awk -v repl="$token" '{gsub(/\${token}/, repl); print}' |
while read …

You can perform the replacement with sed, but only if you're sure that none of the characters &\/ and newline appear in the replacement text $token (you can change the separator character from / to something else if there's another character which you're sure doesn't appear in $token).

<input.txt sed -e "s/\\\${token}/$token/" |
while read …
share|improve this answer

Variables when echoed are not subject to variable expansion. Prepend eval to echo. This might work for simple cases, but can break if your strings contain | or quotes. Or, just do the substitution:

echo ${col1/'${token}'/$token}
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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