字符串连接不适用于逗号字符 [英] String concatenation doesn't work for comma character
问题描述
bash脚本上的字符串连接不适用于逗号,"字符.
String concatenation on bash script doesn't work on comma "," character.
A="Hello";
B=",World";
C=$A$B
echo $C;
将输出打印为
Hello World
Hello World
bash版本为:
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
相同的代码似乎可以在此处
The same code seems to work in here
推荐答案
最可能的解释是您已将 $ IFS
设置为,
The most likely explanation is that you have $IFS
set to ,
解决此问题的最简单方法是 双引号 $ C
,在这种情况下,将传递 echo
值未修改:
The simplest way around this is to double-quote $C
, in which case echo
is passed the value unmodified:
echo "$C"
还请注意,由于每个命令都在其单独的行上,因此您不需要分号来终止命令.
要以明确的格式打印 $ IFS
的当前值,请使用
To print the current value of $IFS
in unambiguous form, use
printf '%q\n' "$IFS" # the default value will print as $' \t\n' - space, tab, newline
关于为什么,
消失:
As for why the ,
disappeared:
- 当您使用未加引号的变量引用(例如
$ C
)时,shell将应用各种- 默认情况下,
$ IFS
包含一个空格,一个制表符和一个换行符,有效地由 whitespace 分隔.- 在您的情况下,
$ IFS
可能包含,
导致Hello,World
分为Hello
和World
,然后作为单独的参数传递给echo
.如前所述,双引号变量引用可以防止这种情况.echo
,当给定多个参数时,总是使用单个空格在输出中将它们分开. - 默认情况下,
- When you use an unquoted variable reference such as
$C
, the shell applies various shell expansions to the value. - Notably, word splitting is applied, which means that the value is split into tokens using any of the characters contained in the special
$IFS
variable as a separator ("IFS" stands for "Internal Field Separator"). - By default,
$IFS
contains a space, a tab, and a newline, effectively splitting by whitespace. - In your case,
$IFS
likely contained,
resulting inHello,World
getting split intoHello
andWorld
, which are then passed toecho
as separate arguments. As stated, double-quoting variable references prevents this behavior. echo
, when given multiple arguments, always uses a single space to separate them on output.
设置 $ IFS
的提示:
Tips for setting $IFS
:
由于 $ IFS
是全局变量,因此在更改后将其恢复为以前的值是一种很好的做法:
Since $IFS
is a global variable, it's good practice to restore it to its previous value after changing it:
prevIFS=$IFS IFS=',' # save old value, set desired value (',', in this example)
# ... perform operations with custom $IFS in effect
IFS=$prevIFS # restore old value
但是,有种技术可以本地化更改,这意味着您不必显式保存和恢复其以前的值:
However, there are techniques that localize the change, which means you do not have to explicitly save and restore its previous value:
如果仅基于外部实用程序或内置的单个命令需要自定义 $ IFS
值-通常为 read
-在命令前添加 IFS = ...
;例如:
If a custom $IFS
value is only needed for a single command based on an external utility or builtin -- typically read
-- prepend IFS=...
to the command; e.g.:
IFS=/ read -r var1 var2 <<<'a/b' # -> $var1 == 'a', $var2 == 'b'
这使更改后的 $ IFS
仅对调用的命令 生效.
This makes the changed $IFS
take effect only for the command invoked.
注意事项:这在更改的IFS值必须在调用内置程序/可执行文件之前必须生效的情况下不起作用,例如使用Shell扩展;例如:
Caveat: This does NOT work in situations where the changed IFS value must take effect BEFORE invoking the builtin / executable, such as with shell expansions; e.g.:
# !! Does NOT work as intended, because $var is expanded BEFORE `IFS=/` takes effect.
var='a/b'; IFS=/ set -- $var
如果要整个功能更改 $ IFS
,但仅 该功能,使用本地 $ IFS
变量,该变量遮盖全局<代码> $ IFS :
Inside a shell function, if you want to change $IFS
for the entire function, but only for that function, use a local $IFS
variable that shadows the global $IFS
:
foo() {
local IFS=/ var1 var2 # $IFS change confined to this function due to `local`
read -r var1 var2 <<<"$1"
echo "[$var1] [$var2]"
}
foo "a/b" # -> '[a] [b]'
如果可行,请将命令列表放在 subshell 中:
If feasible, enclose a list of commands in a subshell:
(arr=(a b); IFS=/; echo "${arr[*]}") # -> 'a/b'
$ IFS
修改仅对子外壳可见.
The $IFS
modification is only visible to subshell.
注意事项:在子shell中修改或创建的变量对于当前shell是不可见的(实际上,这是此技术所依赖的).
Caveat: variables modified or created in the subshell are not visible to the current shell (which is, in fact, what this technique relies on).
这篇关于字符串连接不适用于逗号字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!