bash中的字符串格式

时间:2013-04-16 04:15:05

标签: string bash

我有以下在shell脚本中运行的代码

foo=`seq 1 1 100`
for i in $foo; do
  echo "input$i\_now"
done

这是我的问题:在某些情况下,输出会打印input1_now,而其他输出会打印input1\_now。我确定有些不同,但我无法弄清楚是什么让它以某种方式打印。如果我的代码是

for i in $foo; do
   echo "input$i_now"
done

我将永远得到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

2 个答案:

答案 0 :(得分:3)

_应该是占位符,有时候是一个不同的角色吗?

bash "input$i\_now"中,实际_的{​​{1}}将始终生成input1\_now。在双引号内,bash只会在\$`"之后删除\或换行。见“Double Quotes” in the Bash Reference Manual。这是POSIX标准行为;见“Double-Quotes” in Shell Command Language

更新

如果您写"input$i_now"bash将只打印input。它不会打印input1input1_now。这样做是因为_是有效的参数名称字符,因此bash认为您要求i_now参数的值。除非您已将i_now设置为非空字符串,否则bash会将$i_now展开为空字符串,从而将"input$i_now"转换为input

更新2

现在您已经发布了实际代码,我们可以看到发生了什么。

首先,在你发布的真实代码中,你从未在参数扩展中使用双引号。这有所不同。

在双引号之外,始终会移除\。见“Quote Removal” in the Bash Reference Manual。因此,input$i\_now围绕双引号)会扩展为input1_now

但是,正如我在第一次更新中所解释的那样,_是参数名称字符。见“Name” in Shell Command Language。因此,当bash看到input$i_now时,它会以i_now作为参数名称。

无论您是否使用双引号,必须将参数名称与以下字符分开,如果bash否则将后续字符视为参数名称的一部分。您可以通过将\放在参数名称后面来执行此操作,也可以通过将参数名称放在{...}中来完成此操作。

总是使用{...}更安全,因为(正如您所发现的那样?)\的处理方式不同,具体取决于它是否在双引号内。如果您稍后返回并添加双引号,并且已使用\,则无论如何都需要将\更改为{...}

更新3

以下是\{...}和双引号效果的演示。首先,我们设置了一些变量:

$ year=2004 ptime=1 i=1 sim=123

以下是没有任何引用的情况:

$ echo vect=sim$sim_pts_$year_$ptime_run$i@expSim$sim_$i,sim$sim_pts_$year_$ptime
vect=sim1@expSim1,sim1

如果我们只使用{...}而不使用双引号会发生什么:

$ 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

如果我们添加双引号,它们就没有效果:

$ 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

如果我们只使用\

,会发生什么
$ 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

请注意,每个\都已删除。如果没有引用,shell将删除\

如果我们添加双引号,它们会阻止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

答案 1 :(得分:2)

你需要向bash解释你想要$ i变量:

foo=`seq 1 1 100`
for i in $foo; do
  echo "input${i}_now"
done

区别:

input$i_now    # "input" + $i_now
input${i}_now  # "input" + $i + "_now"