How to concatenate string variables in Bash

后端 未结 30 2035
攒了一身酷
攒了一身酷 2020-11-22 03:40

In PHP, strings are concatenated together as follows:

$foo = \"Hello\";
$foo .= \" World\";

Here, $foo becomes \"Hello World\"

30条回答
  •  傲寒
    傲寒 (楼主)
    2020-11-22 04:18

    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 variable

    The syntax += may be used in different ways:

    Append to string var+=...

    (Because I am frugal, I will only use two variables foo and a and then re-use the same in the whole answer. ;-)

    a=2
    a+=4
    echo $a
    24
    

    Using the Stack Overflow question syntax,

    foo="Hello"
    foo+=" World"
    echo $foo
    Hello World
    

    works fine!

    Append to an integer ((var+=...))

    variable a is a string, but also an integer

    echo $a
    24
    ((a+=12))
    echo $a
    36
    

    Append to an array var+=(...)

    Our a is also an array of only one element.

    echo ${a[@]}
    36
    
    a+=(18)
    
    echo ${a[@]}
    36 18
    echo ${a[0]}
    36
    echo ${a[1]}
    18
    

    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:

    a+=(one word "hello world!" )
    bash: !": event not found
    

    Hmm.. this is not a bug, but a feature... To prevent bash to try to develop !", you could:

    a+=(one word "hello world"! 'hello world!' $'hello world\041')
    
    declare -p a
    declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="h
    ello world!" [6]="hello world!")'
    

    printf: Re-construct variable using the builtin command

    The 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 on stdout:

    echo ${a[@]}
    36 18 one word hello world! hello world! hello world!
    

    There are seven strings in this array. So we could build a formatted string containing exactly seven positional arguments:

    printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
    echo $a
    36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'
    

    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!

    declare -p a
    declare -a a='([0]="36./.18...'\''one'\'' '\''word'\'', '\''hello world!'\''=='\
    ''hello world!'\''=='\''hello world!'\''" [1]="18" [2]="one" [3]="word" [4]="hel
    lo world!" [5]="hello world!" [6]="hello world!")'
    

    Under bash, when you access a variable name without specifying index, you always address first element only!

    So to retrieve our seven field array, we only need to re-set 1st element:

    a=36
    declare -p a
    declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="he
    llo world!" [6]="hello world!")'
    

    One argument format string with many argument passed to:

    printf -v a[0] '<%s>\n' "${a[@]}"
    echo "$a"
    <36>
    <18>
    
    
    
    
    
    

    Using the Stack Overflow question syntax:

    foo="Hello"
    printf -v foo "%s World" $foo
    echo $foo
    Hello World
    

    Nota: The use of double-quotes may be useful for manipulating strings that contain spaces, tabulations and/or newlines

    printf -v foo "%s World" "$foo"
    

    Shell now

    Under POSIX shell, you could not use bashisms, so there is no builtin printf.

    Basically

    But you could simply do:

    foo="Hello"
    foo="$foo World"
    echo $foo
    Hello World
    

    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):

    foo="Hello"
    foo=$(printf "%s World" "$foo")
    echo $foo
    Hello World
    

    Historically, you could use backticks for retrieving result of a fork:

    foo="Hello"
    foo=`printf "%s World" "$foo"`
    echo $foo
    Hello World
    

    But this is not easy for nesting:

    foo="Today is: "
    foo=$(printf "%s %s" "$foo" "$(date)")
    echo $foo
    Today is: Sun Aug 4 11:58:23 CEST 2013
    

    with backticks, you have to escape inner forks with backslashes:

    foo="Today is: "
    foo=`printf "%s %s" "$foo" "\`date\`"`
    echo $foo
    Today is: Sun Aug 4 11:59:10 CEST 2013
    

提交回复
热议问题