String concatenation does not work for comma

String concatenation in bash script does not work with comma "," character.

A="Hello";
B=",World";
C=$A$B
echo $C;

      

It prints the output as

Hello world

Bash version:

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

      

This same code works in here

+1


source to share


1 answer


the most likely explanation is that you have set to $IFS

,

The easiest way is double-quote$C

, in this case echo

the value is passed unmodified:

echo "$C"

      

Also note that you don't need semicolons to break your commands, given that each command is on its own line.


To print the current value$IFS

in an unambiguous manner, use

printf '%q\n' "$IFS"  # the default value will print as $' \t\n' - space, tab, newline

      


As for why it ,

disappeared
:

  • When you use an unquoted reference, for example $C

    , the shell applies different shell extension values to the value.
  • Specifically, word splitting is applied, which means that the value is split into tokens using any of the characters contained in the special variable $IFS

    as the delimiter ("IFS" stands for "Internal Field Separator").
  • $IFS

    Contains space, tab and newline by default , effectively separating spaces.
  • In your case $IFS

    , it most likely contained ,

    , resulting in Hello,World

    split into Hello

    and World

    , which are then passed echo

    in as separate arguments. As stated, double quoted links do not allow this behavior.
  • echo

    when multiple arguments are given, a single space is always used to allocate them on output.

Tips for setting $IFS

:

Since it is a global variable , it is recommended to restore its previous value after changing it: $IFS

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 methods that localize the change , which means you don't need to explicitly save and restore its previous value:




If a custom value $IFS

is only required for a single command based on an external utility or builtin - usually read

- prepend IFS=...

for the command
; eg:.

IFS=/ read -r var1 var2 <<<'a/b'  # -> $var1 == 'a', $var2 == 'b'

      

This causes the changed to be $IFS

effective only for the called command.

Caution . This does NOT work in situations where the changed IFS value needs to take effect BEFORE invoking the embedded / executable, such as with a shell extension; eg:.

 # !! Does NOT work as intended, because $var is expanded BEFORE `IFS=/` takes effect.
var='a/b'; IFS=/ set -- $var

      


Inside a wrapper function , if you want to change $IFS

for the whole 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]'

      


If possible, enclose the command list in a subshell :

(arr=(a b); IFS=/; echo "${arr[*]}") # -> 'a/b'

      

The modification $IFS

is only visible to the subshell.

Caveat : Variables modified or created in the subshell are not visible to the current shell (which is actually what this method relies on).

+6


source







All Articles