如何在 Bash 中连接字符串变量
在 PHP 中,字符串按如下方式连接在一起:
$foo = "Hello";
$foo .= " World";
这里,$foo
变为 "Hello World"
。
这在 Bash 中是如何实现的?
In PHP, strings are concatenated together as follows:
$foo = "Hello";
$foo .= " World";
Here, $foo
becomes "Hello World"
.
How is this accomplished in Bash?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
一般来说,要连接两个变量,您可以将它们一个接一个地写入:
In general to concatenate two variables you can just write them one after another:
Bash 还支持
+=
运算符,如以下代码所示:输出
Bash also supports a
+=
operator as shown in this code:output
首先是 Bash
因为这个问题专门针对 Bash,我的答案的第一部分将提供正确执行此操作的不同方法:
+=
:附加到变量语法
+=
可以以不同的方式使用:附加到字符串
var+=...
(因为我很节俭,所以我只会使用两个变量
foo
和a
,然后在完整答案。;-)使用堆栈溢出问题语法,
效果很好!
附加到整数
((var+=...))
变量
a
是一个字符串,也是一个整数附加到整数声明的变量:
var+=。 ..
在 bash 下,一旦声明变量,您就可以使用整数:
或
附加到数组
var+=(...)
我们的
a
也是一个仅包含一个元素的数组。请注意,括号之间有一个空格分隔的数组。如果要在数组中存储包含空格的字符串,则必须将它们括起来:
嗯.. 这不是一个错误,而是一个错误功能...为了防止 bash 尝试开发
!”
,您可以:其中 6 个字段(
一个
、单词
和 4 xhello world!
),添加到数组$ {ar[@]}
已包含38
和18
注意:您可以< strong>将字符串追加到数组中:
当然,如果
array
被声明为整数,bash将尝试解析整数操作:printf
:重新-使用 builtin 命令构造变量printf
builtin 命令提供了一种绘制字符串格式的强大方法,因为这是 Bash builtin<。 /em>,有一个选项可以将格式化字符串发送到变量,而不是在stdout
上打印:此数组中有七个字符串。因此,我们可以构建一个包含九个位置参数的格式化字符串:
或者我们可以使用一个参数格式字符串,它将重复提交的参数数量...
请注意,我们的
a
仍然是一个数组!仅更改第一个元素!在 bash 下,当您访问变量名而不指定索引时,您始终只寻址第一个元素!
因此,要检索我们的九个字段数组,我们只需要重新设置第一个元素:
一个参数格式字符串,其中传递多个参数:
使用堆栈溢出问题语法:
注意:的使用>双引号对于操作包含
空格
、制表
和/或换行符
的字符串可能很有用,现在在Shell
下 POSIX shell,您不能使用bashisms,因此没有内置的printf。
基本上
但是你可以简单地这样做:
在另一边:
但是如果你想在变量之后立即添加字母,没有空格,你可能需要使用大括号:
格式化,使用分叉
printf
如果你想使用更复杂的结构,你必须使用fork(新的子进程,它完成工作并通过
stdout
返回结果code>):从历史上看,您可以使用反引号来检索分叉的结果:
但这对于嵌套来说并不容易:
使用反引号,您可以必须用反斜杠转义内部分叉:
更多..
玩字符串,看看:
shrinkStr
将通过获取字符串的开头和结尾将字符串长度限制为特定长度。headTail
将通过构建适当的sed
命令获取文件的 head 和 tail。Bash first
As this question stand specifically for Bash, my first part of the answer would present different ways of doing this properly:
+=
: Append to variableThe syntax
+=
may be used in different ways:Append to string
var+=...
(Because I am frugal, I will only use two variables
foo
anda
and then re-use the same in the whole answer. ;-)Using the Stack Overflow question syntax,
works fine!
Append to an integer
((var+=...))
variable
a
is a string, but also an integerAppend to an interger declared variable:
var+=...
Under bash, you could work in integer once variable is declared:
or
Append to an array
var+=(...)
Our
a
is also an array of only one element.Note that between parentheses, there is a space separated array. If you want to store a string containing spaces in your array, you have to enclose them:
Hmm.. this is not a bug, but a feature... To prevent bash to try to develop
!"
, you could:Where 6 fields (
one
,word
and 4 xhello world!
), where added to array${ar[@]}
which already contained38
and18
.Note: you could append to a string into an array:
Of course if
array
is declared as in integer, bash will try to resolve integer operation:printf
: Re-construct variable using the builtin commandThe
printf
builtin command gives a powerful way of drawing string format. As this is a Bash builtin, there is a option for sending formatted string to a variable instead of printing onstdout
:There are seven strings in this array. So we could build a formatted string containing exactly nine positional arguments:
Or we could use one argument format string which will be repeated as many argument submitted...
Note that our
a
is still an array! Only first element is changed!Under bash, when you access a variable name without specifying index, you always address first element only!
So to retrieve our nine field array, we only need to re-set 1st element:
One argument format string with many argument passed to:
Using the Stack Overflow question syntax:
Nota: The use of double-quotes may be useful for manipulating strings that contain
spaces
,tabulations
and/ornewlines
Shell now
Under POSIX shell, you could not use bashisms, so there is no builtin
printf
.Basically
But you could simply do:
In the other side:
But if you want to add letters immediately after your variable, without space, you may need to use braces:
Formatted, using forked
printf
If you want to use more sophisticated constructions you have to use a fork (new child process that make the job and return the result via
stdout
):Historically, you could use backticks for retrieving result of a fork:
But this is not easy for nesting:
with backticks, you have to escape inner forks with backslashes:
More..
Playing with strings, have a look at:
shrinkStr
will limit string length to specific length by taking begin and end of them. andheadTail
will take head and tail of a file by building appropriatesed
command.你也可以这样做:
You can do this too:
将输出
这在以下情况下很有用
$blaohai
导致变量未找到错误。或者如果字符串中有空格或其他特殊字符。
"${foo}"
正确转义您放入其中的任何内容。Will output
This is useful when
$blaohai
leads to a variable not found error. Or if you have spaces or other special characters in your strings.
"${foo}"
properly escapes anything you put into it.以下是大多数答案所讨论内容的简要总结。
假设我们有两个变量,并且 $1 设置为“一”:
下表解释了不同的上下文,我们可以在其中组合
a
和b
的值来创建新变量变量,c
。一些注意事项:
+=
会更好小增量,尤其是在循环中,{}
来消除其扩展的歧义(如上表中的第 2 行所示)。如第 3 行和第 4 行所示,除非变量与以 shell 变量名称中有效第一个字符(即字母表)开头的字符串连接,否则不需要{}
或下划线。另请参阅:
Here is a concise summary of what most answers are talking about.
Let's say we have two variables and $1 is set to 'one':
The table below explains the different contexts where we can combine the values of
a
andb
to create a new variable,c
.A few notes:
+=
is better from a performance standpoint if a big string is being constructed in small increments, especially in a loop{}
around variable names to disambiguate their expansion (as in row 2 in the table above). As seen on rows 3 and 4, there is no need for{}
unless a variable is being concatenated with a string that starts with a character that is a valid first character in shell variable name, that is alphabet or underscore.See also:
我解决问题的方法就是例如
,
它会产生
例如,如果您尝试将一个字符串与另一个字符串连接,
那么
echo "$c"
将产生一个额外的空格。
并不像你想象的那样工作,但
会产生
The way I'd solve the problem is just
For example,
which produces
If you try to concatenate a string with another string, for example,
then
echo "$c"
will producewith an extra space.
doesn't work, as you may imagine, but
produces
另一种方法……
又一种方法。
Yet another approach...
...and yet yet another one.
如果您想附加下划线之类的内容,请使用转义符 (\)
这不起作用:
这工作正常:
If you want to append something like an underscore, use escape (\)
This does not work:
This works fine:
最简单的加引号的方式:
The simplest way with quotation marks:
即使现在允许使用 += 运算符,它也是在 2004 年的 Bash 3.1 中引入的。
如果幸运的话,在较旧的 Bash 版本上使用此运算符的任何脚本都会失败,并出现“找不到命令”错误,或“意外标记附近的语法错误”。
对于那些关心向后兼容性的人,请坚持使用较旧的标准 Bash 连接方法,如所选答案中提到的方法:
Even if the += operator is now permitted, it has been introduced in Bash 3.1 in 2004.
Any script using this operator on older Bash versions will fail with a "command not found" error if you are lucky, or a "syntax error near unexpected token".
For those who cares about backward compatibility, stick with the older standard Bash concatenation methods, like those mentioned in the chosen answer:
默认情况下,Bash 中的变量和数组(索引或关联*)始终是字符串,但您可以使用
declare
内置标志,为它们提供诸如“整数”之类的属性(-i) 或“引用”** (
-n
),这会改变它们的行为方式。Bash 算术接受 ASCII/字符串数字作为输入,因此几乎没有理由实际使用整数属性。
另外,变量值不能包含 ASCII
NULL
(即 8 位零),因为使用常规的 null 终止 C 字符串来实现它们。* 即一个或多个键+值对。
** 引用变量扩展为另一个变量的值,该变量的标签分配给引用变量
附加字符串:
使用整数属性的几个原因之一是,它改变了引用变量的行为
+=
赋值运算符:请注意,这不适用于
-=
、/=
等,除非您在算术内部执行此操作(< code>(( )) 和$(( ))
),其中无论是否带有整数属性,数字都已被视为相同。有关这些运算符的完整列表,请参阅man bash
的“算术求值”部分,这些运算符与 C 中的相同。+=
赋值运算符也可以用于将新元素附加到索引数组(又名“列表”):执行此操作的另一种常见方法是使用计数器:
POSIX shell不使用< code>+= 赋值运算符附加字符串,所以你必须这样做:
这在 Bash 中也很好,所以它可以被认为是一种更可移植的语法。
Variables and arrays (indexed or associative*) in Bash are always strings by default, but you can use flags to the
declare
builtin, to give them attributes like "integer" (-i
) or "reference"** (-n
), which change the way they behave.Bash arithmetic accepts ASCII/string numbers for input, so there are few reasons to actually use the integer attribute.
Also, variable values can't contain ASCII
NULL
(i.e., 8 bit zero), because regular null terminated C strings are used to implement them.* Ie one or more key + value pairs.
** Reference variables expand to the value of another variable, whose label is assigned to the reference variable
Append a string:
One of the few reasons to use the integer attribute, is that it changes the behaviour of the
+=
assignment operator:Note that this doesn't work for
-=
,/=
, etc. unless you do it inside arithmetic ((( ))
and$(( ))
), where numbers are already treated the same with or without the integer attribute. See the section "arithmetic evaluation" ofman bash
for a full list of those operators, which are the same as for C.The
+=
assignment operator can also be used to append new elements to an indexed array (AKA "list"):Another common way to do this is to use a counter:
POSIX shells do not use the
+=
assignment operator to append strings, so you have to do it like this:This is fine in Bash too, so it could be considered a more portable syntax.
您可以不使用引号进行连接。下面是一个示例:
最后一条语句将打印“OpenSystems”(不带引号)。
这是 Bash 脚本的示例:
You can concatenate without the quotes. Here is an example:
This last statement would print "OpenSystems" (without quotes).
This is an example of a Bash script:
我更喜欢使用大括号
${}
来扩展字符串中的变量:大括号适合连续字符串使用:
否则使用
foo = "$fooWorld"
将不起作用。I prefer to use curly brackets
${}
for expanding variable in string:Curly brackets will fit to Continuous string usage:
Otherwise using
foo = "$fooWorld"
will not work.尽管有特殊的运算符
+=
用于连接,但还有一种更简单的方法:双引号需要额外的计算时间来解释内部变量。如果可能的话避免它。
Despite of the special operator,
+=
, for concatenation, there is a simpler way to go:Double quotes take an extra calculation time for interpretation of variables inside. Avoid it if possible.
更安全的方法:
包含空格的字符串可以成为命令的一部分,使用“$XXX”和“${XXX}”来避免这些错误。
另外看看关于+=的其他答案
Safer way:
Strings containing spaces can become part of command, use "$XXX" and "${XXX}" to avoid these errors.
Plus take a look at other answer about +=
您应该注意一种特殊情况:
将输出
"daniel"san
,而不是您可能想要的danielsan
。在这种情况下,你应该这样做:
There's one particular case where you should take care:
Will output
"daniel"san
, and notdanielsan
, as you might have wanted.In this case you should do instead:
如果您想要将一个字符串分割为多行,则可以使用反斜杠:
中间有一个空格:
这也仅在中间添加一个空格:
If what you are trying to do is to split a string into several lines, you can use a backslash:
With one space in between:
This one also adds only one space in between:
有人表达了对性能的担忧,但没有提供任何数据。让我建议一个简单的测试。
(注意:macOS 上的
date
不提供纳秒,因此必须在 Linux 上完成。)我创建了 GitHub 上的append_test.sh,内容为:
测试 1:
测试 2:
错误表明我的 Bash 在崩溃之前达到了 335.54432 MB。您可以将代码从将数据加倍更改为附加常量以获得更精细的图表和失败观点。但我认为这应该为您提供足够的信息来决定您是否关心。就我个人而言,低于 100MB 我不会。您的里程可能会有所不同。
There are voiced concerns about performance, but no data is offered. Let me suggest a simple test.
(NOTE:
date
on macOS does not offer nanoseconds, so this must be done on Linux.)I have created append_test.sh on GitHub with the contents:
Test 1:
Test 2:
The errors indicate that my Bash got up to 335.54432 MB before it crashed. You could change the code from doubling the data to appending a constant to get a more granular graph and failure point. But I think this should give you enough information to decide whether you care. Personally, below 100 MB I don't. Your mileage may vary.
这就是连接两个字符串的方法。
This is how you concatenate two strings.
如果它是在原始字符串中添加
" World"
的示例,那么它可以是:输出:
If it is as your example of adding
" World"
to the original string, then it can be:The output:
我想从列表中构建一个字符串。找不到答案,所以我将其发布在这里。这就是我所做的:
然后我得到以下输出:
I wanted to build a string from a list. Couldn't find an answer for that so I post it here. Here is what I did:
and then I get the following output:
请注意,这不起作用
,因为它似乎会删除 $foo 并留下:
但这会起作用:
并为您留下正确的输出:
Note that this won't work
as it seems to drop $foo and leaves you with:
but this will work:
and leave you with the correct output:
以下是 AWK 的内容:
Here is the one through AWK:
我在方便的时候这样做:使用内联命令!
I do it this way when convenient: Use an inline command!
在我看来,连接两个字符串的最简单方法是编写一个为您执行此操作的函数,然后使用该函数。
In my opinion, the simplest way to concatenate two strings is to write a function that does it for you, then use that function.
还可以在 Bash 4.x 中使用
命名引用
,将任意字符串添加到引用的字符串中(每个字符串由引用的分隔符分隔):像这样使用它:
另一种追加(和分隔)的方法) 与 `printf`:
There's also the possibility to use
named references
in Bash 4.x, to add arbitrary strings to the referenced string (delimited by a referenced separator each):Use it like so:
Another way to append (and separate) with `printf``: