string bash中的字符串格式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16028677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 01:53:01  来源:igfitidea点击:

string formatting in bash

stringbash

提问by ShaunLangley

I have the following code that runs in a shell script

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

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_nowwhereas 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

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

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

I will always get inputwith the rest of the line being omitted.

我总是会input忽略该行的其余部分。

I know I can use input${i}_nowinstead and have it print correctly every time, but I'm mostly interested in understanding why the output is different under seemingly the same conditions.

我知道我可以input${i}_now改用并每次都正确打印,但我最感兴趣的是理解为什么在看似相同的条件下输出不同。

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

回答by sastorsl

You need to explain to bash that you want the $i variable:

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

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

The difference:

区别:

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

回答by rob mayoff

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, bashonly 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.

bash"input$i\_now"用实际_总会产生的input1\_now。在双引号内,bash\当 a 后跟 a $、 a `、 a "、 a\或换行符时才删除 a 。请参阅Bash 参考手册中的“双引号”。这是 POSIX 标准行为;请参阅Shell 命令语言中的“双引号”

UPDATE

更新

If you write "input$i_now", bashwill just print input. It will not print input1or input1_now. It does this because _is a valid parameter name character, so bashthinks you are asking for the value of the i_nowparameter. Unless you have set i_nowto a non-empty string, bashwill expand $i_nowto the empty string, thus turning "input$i_now"into input.

如果你写"input$i_now"bash只会打印input。它不会打印input1input1_now。它这样做是因为它_是一个有效的参数名称字符,所以bash认为您是在要求i_now参数的值。除非你已经设置i_now为非空字符串,bash否则会扩展$i_now为空字符串,从而"input$i_now"变成input.

UPDATE 2

更新 2

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 nosurrounding double-quotes) expands to input1_now.

在双引号之外,a\总是被删除。请参阅Bash 参考手册中的“引用删除”。因此input$i\_now没有周围的双引号)扩展为input1_now.

However, as I explained in my first update, _is a parameter name character. See “Name”?in Shell Command Language. So when bashsees input$i_now, it takes i_nowas the parameter name.

但是,正如我在第一次更新中所解释的,_是参数名称字符。见“名称”?在shell命令行语言。所以当bash看到时input$i_now,它i_now作为参数名称。

Whether or not you're using double-quotes, you mustseparate the parameter name from the following character, if bashwould 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 {...}.

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

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.

始终使用 更安全{...},因为(正如您所发现的?)\根据它是否在双引号内而有不同的处理方式。如果您稍后返回并添加双引号,并且您使用了\,则无论如何您都需要将 更改\{...}

UPDATE 3

更新 3

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.

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

If we add double-quotes, they prevent the shell from removing each \:

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