I have the following code that runs in a shell script
foo=`seq 1 1 100`
for i in $foo; do
echo "input$i\_now"
done
Here's my question: Under some conditions, the output prints input1_now
whereas othertimes it prints input1\_now
. I'm sure something is different, but I can't figure out what makes it print one way or the other. If my code is
for i in $foo; do
echo "input$i_now"
done
I will always get input
with the rest of the line being omitted.
I know I can use input${i}_now
instead and have it print correctly every time, but I'm mostly interested in understanding why the output is different under seemingly the same conditions.
UPDATE:
In the following example, the first part correctly formats the variables and text such that the \_
is replaced as _
. However, the last part required me to place variables in curly brackets in order to have them formatted correctly.
echo "Enter Simulation #: "
read sim
g.mapset results
for i in `seq 1 1 100`; do
file=sim$sim\_run$i\_sum
g.copy $file\@expSim$sim\_$i,$file
file=sim$sim\_run$i\_average
g.copy $file\@expSim$sim\_$i,$file
for year in `seq 2004 1 2006`; do
file=sim$sim\_$year\_run$i\_sum
g.copy $file\@expSim$sim\_$i,$file
file=sim$sim\_$year\_run$i\_average
g.copy $file\@expSim$sim\_$i,$file
done
years="2004 2005 2006"
times=`seq -w 1 16 365`
runs=`seq 1 1 100`
for year in $years; do
for ptime in $times; do
for i in $runs; do
if [ $i -eq 1 ]; then
g.copy vect=sim${sim}_pts_${year}_${ptime}_run${i}@expSim${sim}_${i},sim${sim}_pts_${year}_${ptime}
fi
if [ $i -gt 1 ]; then
v.patch input=sim${sim}_pts_${year}_${ptime}_run${i}@expSim${sim}_${i} output=sim${sim}_pts_${year}_${ptime} -e -a --o
fi
done
done
done
Is _
supposed to be a placeholder that is sometimes a different character?
In bash
, "input$i\_now"
with an actual _
will always produce input1\_now
. Inside double-quotes, bash
only removes a \
when it is followed by a $
, a `
, a "
, a \
, or a newline. See “Double Quotes” in the Bash Reference Manual. This is the POSIX standard behavior; see “Double-Quotes” in Shell Command Language.
If you write "input$i_now"
, bash
will just print input
. It will not print input1
or input1_now
. It does this because _
is a valid parameter name character, so bash
thinks you are asking for the value of the i_now
parameter. Unless you have set i_now
to a non-empty string, bash
will expand $i_now
to the empty string, thus turning "input$i_now"
into input
.
Now that you have posted real code, we can see what's going on.
First of all, in the real code you posted, you never used double-quotes around a parameter expansion. This makes a difference.
Outside of double-quotes, a \
is always removed. See “Quote Removal” in the Bash Reference Manual. Hence input$i\_now
(with no surrounding double-quotes) expands to input1_now
.
However, as I explained in my first update, _
is a parameter name character. See “Name” in Shell Command Language. So when bash
sees input$i_now
, it takes i_now
as the parameter name.
Whether or not you're using double-quotes, you must separate the parameter name from the following character, if bash
would otherwise treat the following character as part of the parameter name. You can do this by putting \
after the parameter name, or you can do it by putting the parameter name in {...}
.
It is safer to always use {...}
, because (as you have discovered?) \
is handled differently depending on whether it's inside double-quotes. If you go back and add double-quotes later, and you have used \
, you will need to change the \
to {...}
anyway.
Here is a demonstration of the effects of \
, {...}
, and double-quoting. First, we set up some variables:
$ year=2004 ptime=1 i=1 sim=123
Here's what happens with no quoting whatsoever:
$ echo vect=sim$sim_pts_$year_$ptime_run$i@expSim$sim_$i,sim$sim_pts_$year_$ptime
vect=sim1@expSim1,sim1
Here's what happens if we just use {...}
without double-quotes:
$ echo vect=sim${sim}_pts_${year}_${ptime}_run${i}@expSim${sim}_${i},sim${sim}_pts_${year}_${ptime}
vect=sim123_pts_2004_1_run1@expSim123_1,sim123_pts_2004_1
If we add double-quotes, they have no effect:
$ echo "vect=sim${sim}_pts_${year}_${ptime}_run${i}@expSim${sim}_${i},sim${sim}_pts_${year}_${ptime}"
vect=sim123_pts_2004_1_run1@expSim123_1,sim123_pts_2004_1
Here's what happens if we just use \
:
$ echo vect=sim$sim\_pts\_$year\_$ptime\_run$i@expSim$sim\_$i,sim$sim\_pts\_$year\_$ptime
vect=sim123_pts_2004_1_run1@expSim123_1,sim123_pts_2004_1
Notice that each \
was removed. The shell removes a \
if it's not quoted.
If we add double-quotes, they prevent the shell from removing each \
:
$ echo "vect=sim$sim\_pts\_$year\_$ptime\_run$i@expSim$sim\_$i,sim$sim\_pts\_$year\_$ptime"
vect=sim123\_pts\_2004\_1\_run1@expSim123\_1,sim123\_pts\_2004\_1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With