首页 文章

如何在Bash中连接字符串变量

提问于
浏览
2247

在PHP中,字符串连接在一起如下:

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

在这里, $foo 变为"Hello World" .

如何在Bash中完成?

28 回答

  • 1
    bla=hello
    laber=kthx
    echo "${bla}ohai${laber}bye"
    

    会输出

    helloohaikthxbye
    

    $blaohai 导致变量未找到错误时,这很有用 . 或者如果字符串中有空格或其他特殊字符 . "${foo}" 正确地逃避你投入的任何东西 .

  • -1

    Bash还支持a =运算符,如以下脚本所示:

    $ A="X Y"
    $ A+="Z"
    $ echo "$A"
    X YZ
    
  • 18
    foo="Hello"
    foo="$foo World"
    echo $foo
    > Hello World
    

    通常,要连接两个变量,您可以一个接一个地编写它们:

    a='hello'
    b='world'
    c="$a$b"
    echo $c
    > helloworld
    
  • 1

    如果它是将 " World" 添加到原始字符串的示例,那么它可以是:

    #!/bin/bash
    
    foo="Hello"
    foo=$foo" World"
    echo $foo
    

    输出:

    Hello World
    
  • 13

    您可以尝试以下方式 . 当替换发生时,双引号将保留空格 .

    var1="Ram "    
    var2="Lakshmana" 
    echo $var1$var2
    or 
    echo var1+=$var2 "bash support += operation.
    
    bcsmc2rtese001 [/tmp]$ var1="Ram "  
    bcsmc2rtese001 [/tmp]$ var2="Lakshmana"  
    bcsmc2rtese001 [/tmp]$ echo $var1$var2  
    Ram Lakshmana  
    
    bcsmc2rtese001 [/tmp]$ var1+=$var2  
    bcsmc2rtese001 [/tmp]$ echo $var1  
    Ram Lakshmana
    
  • 13

    如果你要做的就是分裂一个将字符串分成几行,可以使用反斜杠:

    $ a="hello\
    > world"
    $ echo $a
    helloworld
    

    中间有一个空格:

    $ a="hello \
    > world"
    $ echo $a
    hello world
    

    这个也只增加了一个空格:

    $ a="hello \
    >      world"
    $ echo $a
    hello world
    
  • 2

    即使现在允许=运算符,它也已在2004年的 Bash 3.1 中引入 .

    在较旧的Bash版本上使用此运算符的任何脚本都将失败,如果您幸运的话,“找不到命令”错误,或者“意外令牌附近的语法错误” .

    对于那些关心向后兼容性的人,请坚持使用旧的标准Bash级联方法,如所选答案中提到的那些:

    foo="Hello"
    foo="$foo World"
    echo $foo
    > Hello World
    
  • 3049
    $ a=hip
    $ b=hop
    $ ab=$a$b
    $ echo $ab
    hiphop
    $ echo $a$b
    hiphop
    
  • 1
    foo="Hello "
    foo="$foo World"
    
  • 5

    引号最简单的方法:

    B=Bar
    b=bar
    var="$B""$b""a"
    echo "Hello ""$var"
    
  • 30

    如果你想追加下划线之类的东西,请使用escape(\)

    FILEPATH=/opt/myfile
    

    这不起作用:

    echo $FILEPATH_$DATEX
    

    这很好用:

    echo $FILEPATH\\_$DATEX
    
  • 110

    又一种方法......

    > H="Hello "
    > U="$H""universe."
    > echo $U
    Hello universe.
    

    ......还有一个 .

    > H="Hello "
    > U=$H"universe."
    > echo $U
    Hello universe.
    
  • 849

    我还不了解PHP,但这适用于Linux Bash . 如果您不想将其影响到变量,可以尝试这样做:

    read pp;  *# Assumes I will affect Hello to pp*
    pp=$( printf $pp ;printf ' World'; printf '!');
    echo $pp;
    
    >Hello World!
    

    你可以放置另一个变量而不是'Hello'或'!' . 您也可以连接更多字符串 .

  • 2

    我有点像快速功能 .

    #! /bin/sh -f
    function combo() {
        echo $@
    }
    
    echo $(combo 'foo''bar')
    

    另一种给猫皮肤的方法 . 这次有功能:D

  • 6

    人们对性能表示担忧,但没有提供数据 . 我建议一个简单的测试 .

    (注意:macOS上的 date 不提供纳秒,因此必须在Linux上完成 . )

    我创建了append_test.sh on GitHub的内容:

    #!/bin/bash -e
    
    output(){
        ptime=$ctime;
        ctime=$(date +%s.%N);
        delta=$(bc <<<"$ctime - $ptime");
        printf "%2s. %16s chars  time: %s  delta: %s\n" $n "$(bc <<<"10*(2^$n)")" $ctime $delta;
    }
    
    method1(){
        echo 'Method: a="$a$a"'
        for n in {1..32}; do a="$a$a"; output; done
    }
    
    method2(){
        echo 'Method: a+="$a"'
        for n in {1..32}; do a+="$a";  output; done
    }
    
    ctime=0; a="0123456789"; time method$1
    

    测试1:

    $ ./append_test.sh 1
    Method: a="$a$a"
     1.               20 chars  time: 1513640431.861671143  delta: 1513640431.861671143
     2.               40 chars  time: 1513640431.865036344  delta: .003365201
     3.               80 chars  time: 1513640431.868200952  delta: .003164608
     4.              160 chars  time: 1513640431.871273553  delta: .003072601
     5.              320 chars  time: 1513640431.874358253  delta: .003084700
     6.              640 chars  time: 1513640431.877454625  delta: .003096372
     7.             1280 chars  time: 1513640431.880551786  delta: .003097161
     8.             2560 chars  time: 1513640431.883652169  delta: .003100383
     9.             5120 chars  time: 1513640431.886777451  delta: .003125282
    10.            10240 chars  time: 1513640431.890066444  delta: .003288993
    11.            20480 chars  time: 1513640431.893488326  delta: .003421882
    12.            40960 chars  time: 1513640431.897273327  delta: .003785001
    13.            81920 chars  time: 1513640431.901740563  delta: .004467236
    14.           163840 chars  time: 1513640431.907592388  delta: .005851825
    15.           327680 chars  time: 1513640431.916233664  delta: .008641276
    16.           655360 chars  time: 1513640431.930577599  delta: .014343935
    17.          1310720 chars  time: 1513640431.954343112  delta: .023765513
    18.          2621440 chars  time: 1513640431.999438581  delta: .045095469
    19.          5242880 chars  time: 1513640432.086792464  delta: .087353883
    20.         10485760 chars  time: 1513640432.278492932  delta: .191700468
    21.         20971520 chars  time: 1513640432.672274631  delta: .393781699
    22.         41943040 chars  time: 1513640433.456406517  delta: .784131886
    23.         83886080 chars  time: 1513640435.012385162  delta: 1.555978645
    24.        167772160 chars  time: 1513640438.103865613  delta: 3.091480451
    25.        335544320 chars  time: 1513640444.267009677  delta: 6.163144064
    ./append_test.sh: fork: Cannot allocate memory
    

    测试2:

    $ ./append_test.sh 2
    Method: a+="$a"
     1.               20 chars  time: 1513640473.460480052  delta: 1513640473.460480052
     2.               40 chars  time: 1513640473.463738638  delta: .003258586
     3.               80 chars  time: 1513640473.466868613  delta: .003129975
     4.              160 chars  time: 1513640473.469948300  delta: .003079687
     5.              320 chars  time: 1513640473.473001255  delta: .003052955
     6.              640 chars  time: 1513640473.476086165  delta: .003084910
     7.             1280 chars  time: 1513640473.479196664  delta: .003110499
     8.             2560 chars  time: 1513640473.482355769  delta: .003159105
     9.             5120 chars  time: 1513640473.485495401  delta: .003139632
    10.            10240 chars  time: 1513640473.488655040  delta: .003159639
    11.            20480 chars  time: 1513640473.491946159  delta: .003291119
    12.            40960 chars  time: 1513640473.495354094  delta: .003407935
    13.            81920 chars  time: 1513640473.499138230  delta: .003784136
    14.           163840 chars  time: 1513640473.503646917  delta: .004508687
    15.           327680 chars  time: 1513640473.509647651  delta: .006000734
    16.           655360 chars  time: 1513640473.518517787  delta: .008870136
    17.          1310720 chars  time: 1513640473.533228130  delta: .014710343
    18.          2621440 chars  time: 1513640473.560111613  delta: .026883483
    19.          5242880 chars  time: 1513640473.606959569  delta: .046847956
    20.         10485760 chars  time: 1513640473.699051712  delta: .092092143
    21.         20971520 chars  time: 1513640473.898097661  delta: .199045949
    22.         41943040 chars  time: 1513640474.299620758  delta: .401523097
    23.         83886080 chars  time: 1513640475.092311556  delta: .792690798
    24.        167772160 chars  time: 1513640476.660698221  delta: 1.568386665
    25.        335544320 chars  time: 1513640479.776806227  delta: 3.116108006
    ./append_test.sh: fork: Cannot allocate memory
    

    这些错误表明我的Bash在崩溃之前已经达到 335.54432 MB . 您可以将the code更改为将数据加倍以附加常量以获得更精细的图形和故障点 . 但我认为这应该给你足够的信息来决定你是否关心 . 就个人而言,低于100 MB,我没有 . 你的旅费可能会改变 .

  • -4

    首先

    Bash

    由于这个问题专门针对Bash,我的答案的第一部分将提出不同的方法来正确地做到这一点:

    =:附加到变量

    语法 += 可以以不同方式使用:

    追加到字符串var = ...

    (因为我节俭,我只会使用两个变量 fooa ,然后在整个答案中重复使用相同的内容 . ;-)

    a=2
    a+=4
    echo $a
    24
    

    使用Stack Overflow问题语法,

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

    工作良好!

    附加到整数((var = ...))

    变量 a 是一个字符串,但也是一个整数

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

    追加到数组var =(...)

    我们的 a 也只是一个元素的数组 .

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

    请注意,在括号之间,有一个空格分隔的数组 . 如果要在数组中存储包含空格的字符串,则必须将它们括起来:

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

    嗯...... this is not a bug, but a feature ...为了防止bash试图开发 !" ,你可以:

    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:使用builtin命令重构变量

    printf builtin命令提供了一种绘制字符串格式的强大方法 . 由于这是一个Bash内置,有一个选项可以将格式化的字符串发送到变量而不是在 stdout 上打印:

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

    这个数组中有七个字符串 . 所以我们可以构建一个包含七个位置参数的格式化字符串:

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

    或者我们可以使用一个参数格式字符串,该字符串将重复提交多个参数...

    请注意,我们的 a 仍然是一个数组!只有第一个元素被改变了!

    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!")'
    

    在bash下,当您在不指定索引的情况下访问变量名时,您始终只能查询第一个元素!

    所以要检索我们的七个字段数组,我们只需要重新设置第一个元素:

    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!")'
    

    传递给许多参数的一个参数格式字符串:

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

    使用Stack Overflow问题语法:

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

    注意:使用双引号可能对操作包含 spacestabulations 和/或 newlines 的字符串很有用

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

    壳牌现在

    在POSIX shell下,您无法使用bashisms,因此没有内置 printf .

    基本上

    但你可以这样做:

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

    格式化,使用forked printf

    如果你想使用更复杂的结构,你必须使用fork(创建作业的新子进程并通过 stdout 返回结果):

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

    从历史上看,您可以使用反引号来检索fork的结果:

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

    但这对于嵌套来说并不容易:

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

    使用反斜杠,你必须用反斜杠逃避内叉:

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

    更安全的方式:

    a="AAAAAAAAAAAA"
    b="BBBBBBBBBBBB"
    c="CCCCCCCCCCCC"
    d="DD DD"
    s="${a}${b}${c}${d}"
    echo "$s"
    AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
    

    包含空格的字符串可以成为命令的一部分,使用“$ XXX”和“$ ”来避免这些错误 .

    再看看关于 += 的其他答案

  • 24

    我方便的时候这样做:使用内联命令!

    echo "The current time is `date`"
    echo "Current User: `echo $USER`"
    
  • 12
    var1='hello'
    var2='world'
    var3=$var1" "$var2 
    echo $var3
    
  • 978

    你也可以这样做:

    $ var="myscript"
    
    $ echo $var
    
    myscript
    
    
    $ var=${var}.sh
    
    $ echo $var
    
    myscript.sh
    
  • 18

    请注意,这不起作用

    foo=HELLO
    bar=WORLD
    foobar=PREFIX_$foo_$bar
    

    因为它似乎放弃了$ foo并离开你:

    PREFIX_WORLD

    但这会奏效:

    foobar=PREFIX_"$foo"_"$bar"
    

    并留下正确的输出:

    PREFIX_HELLO_WORLD

  • 38

    这是一个通过AWK

    $ foo="Hello"
    $ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
    $ echo $foo
    Hello World
    
  • 14

    我更喜欢使用大括号 ${} 来扩展字符串中的变量:

    foo="Hello"
    foo="${foo} World"
    echo $foo
    > Hello World
    

    卷曲括号适合连续字符串使用:

    foo="Hello"
    foo="${foo}World"
    echo $foo
    > HelloWorld
    

    否则使用 foo = "$fooWorld" 将无法正常工作 .

  • 17

    以下是大多数答案所讨论的简明摘要 .

    假设我们有两个变量:

    a=hello
    b=world
    

    下表解释了我们可以将 ab 的值组合在一起以创建新变量 c 的不同上下文 .

    Context                               | Expression            | Result (value of c)
    --------------------------------------+-----------------------+---------------------
    Two variables                         | c=$a$b                | helloworld
    A variable and a literal              | c=${a}_world          | hello_world
    A variable, a literal, with a space   | c=${a}" world"        | hello world
    A more complex expression             | c="${a}_one|${b}_2"   | hello_one|world_2
    Using += operator (Bash 3.1 or later) | c=$a; c+=$b           | helloworld
    Append literal with +=                | c=$a; c+=" world"     | hello world
    

    几点说明:

    • 用双引号括起一个赋值的RHS通常是一个好习惯,尽管在许多情况下它是非常可选的
      如果以较小的增量构造一个大字符串,尤其是在一个循环中,从性能的角度来看

    • += 会更好

    • 使用 {} 围绕变量名来消除其扩展的歧义(如上表中的第2行)


    也可以看看:

  • 5

    有一个特殊情况需要注意:

    user=daniel
    cat > output.file << EOF
    "$user"san
    EOF
    

    将输出 "daniel"san ,而不是 danielsan ,就像您可能想要的那样 . 在这种情况下,你应该做:

    user=daniel
    cat > output.file << EOF
    ${user}san
    EOF
    
  • 0

    我想从列表中构建一个字符串 . 无法找到答案,所以我在这里发布 . 这是我做的:

    list=(1 2 3 4 5)
    string=''
    
    for elm in "${list[@]}"; do
        string="${string} ${elm}"
    done
    
    echo ${string}
    

    然后我得到以下输出:

    1 2 3 4 5
    
  • 7

    我解决问题的方法就是

    $a$b
    

    例如,

    a="Hello"
    b=" World"
    c=$a$b
    echo "$c"
    

    哪个产生

    Hello World
    

    例如,如果您尝试将字符串与另一个字符串连接起来,

    a="Hello"
    c="$a World"
    

    然后 echo "$c" 将产生

    Hello World
    

    有一个额外的空间 .

    $aWorld
    

    你可能想象不起作用,但是

    ${a}World
    

    产生

    HelloWorld
    
  • 119

    您可以在没有引号的情况下连接 . 这是一个例子:

    $Variable1 Open
    $Variable2 Systems
    $Variable3 $Variable1$Variable2
    $echo $Variable3
    

    最后一个语句将打印“OpenSystems”(没有引号) .

    这是Bash脚本的示例:

    v1=hello
    v2=world
    v3="$v1       $v2"
    echo $v3            # Output: hello world
    echo "$v3"          # Output: hello       world
    

相关问题