我有以下在 shell 脚本中运行的代码
foo=`seq 1 1 100`
for i in $foo; do
echo "input$i\_now"
done
Run Code Online (Sandbox Code Playgroud)
这是我的问题:在某些情况下,输出会打印,input1_now而有时会打印input1\_now. 我确定有些东西是不同的,但我无法弄清楚是什么让它以一种或另一种方式打印。如果我的代码是
for i in $foo; do
echo "input$i_now"
done
Run Code Online (Sandbox Code Playgroud)
我总是会input忽略该行的其余部分。
我知道我可以input${i}_now改用并让它每次都正确打印,但我最感兴趣的是理解为什么在看似相同的条件下输出不同。
更新:
在以下示例中,第一部分正确设置了变量和文本的格式,以便将\_替换为_。但是,最后一部分要求我将变量放在大括号中,以便正确格式化它们。
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
Run Code Online (Sandbox Code Playgroud)
被_认为是一个占位符,有时是一个不同的角色?
在bash,"input$i\_now"用实际_总会产生的input1\_now。在双引号内,bash仅\当 a 后跟 a $、 a `、 a "、 a\或换行符时才删除 a 。请参阅Bash 参考手册中的“双引号”。这是 POSIX 标准行为;请参阅Shell 命令语言中的“双引号”。
如果你写"input$i_now",bash只会打印input。它不会打印input1或input1_now。它这样做是因为它_是一个有效的参数名称字符,所以bash认为您是在要求i_now参数的值。除非你已经设置i_now为非空字符串,bash否则会扩展$i_now为空字符串,从而"input$i_now"变成input.
现在您已经发布了真正的代码,我们可以看看发生了什么。
首先,在您发布的实际代码中,您从未在参数扩展周围使用双引号。这有所作为。
在双引号之外,a\总是被删除。请参阅Bash 参考手册中的“引用删除”。因此input$i\_now(没有周围的双引号)扩展为input1_now.
但是,正如我在第一次更新中所解释的,_是参数名称字符。请参阅Shell 命令语言中的“名称”。所以当bash看到时input$i_now,它i_now作为参数名称。
无论您是否使用双引号,您都必须将参数名称与后面的字符分开,否则bash会将后面的字符视为参数名称的一部分。您可以通过将\参数名称放在后面来执行此操作,也可以通过将参数名称放在{...}.
始终使用 更安全{...},因为(正如您发现的那样?)\根据它是否在双引号内进行不同的处理。如果您稍后返回并添加双引号,并且您使用了\,则无论如何您都需要将 更改\为{...}。
这里是的效果演示\,{...}以及双引号。首先,我们设置一些变量:
$ year=2004 ptime=1 i=1 sim=123
Run Code Online (Sandbox Code Playgroud)
这是不引用任何内容时发生的情况:
$ echo vect=sim$sim_pts_$year_$ptime_run$i@expSim$sim_$i,sim$sim_pts_$year_$ptime
vect=sim1@expSim1,sim1
Run Code Online (Sandbox Code Playgroud)
如果我们{...}不使用双引号,会发生以下情况:
$ 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
Run Code Online (Sandbox Code Playgroud)
如果我们添加双引号,它们没有效果:
$ 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
Run Code Online (Sandbox Code Playgroud)
如果我们只使用,会发生以下情况\:
$ 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
Run Code Online (Sandbox Code Playgroud)
请注意,每个都\被删除了。\如果没有引用,shell 将删除 a 。
如果我们添加双引号,它们会阻止 shell 删除每个\:
$ 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
Run Code Online (Sandbox Code Playgroud)
您需要向 bash 解释您想要 $i 变量:
foo=`seq 1 1 100`
for i in $foo; do
echo "input${i}_now"
done
Run Code Online (Sandbox Code Playgroud)
区别:
input$i_now # "input" + $i_now
input${i}_now # "input" + $i + "_now"
Run Code Online (Sandbox Code Playgroud)