webdevqa.jp.net

Bashで文字列変数を連結する方法

PHPでは、文字列は次のように連結されています。

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

ここで$fooは "Hello World"になります。

これはBashでどのように達成されますか?

2423
Strawberry
foo="Hello"
foo="$foo World"
echo $foo
> Hello World

一般的に2つの変数を連結するには、それらを次々に書くことができます。

a='hello'
b='world'
c="$a$b"
echo $c
> helloworld
3285
codaddict

このコードに示すように、Bashは+=演算子もサポートします。

$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
1026
thkala

先にバッシュ

この質問が Bash のために特に立つので、答えの私の最初の部分はこれをきちんとする異なる方法を提示するでしょう:

+=:変数に追加

構文+=は、さまざまな方法で使用できます。

文字列に追加するvar+=...

(私は質素なので、2つの変数fooaのみを使用し、それから答え全体で同じものを再使用します。;-)

a=2
a+=4
echo $a
24

Stack Overflow question構文を使用して、

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

正常に動作します!

整数に追加する((var+=...))

変数aは文字列ですが整数でもあります

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

配列に追加するvar+=(...)

私たちのaも1つの要素だけの配列です。

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

うーん.. これはバグではありませんが、機能です ... 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組み込みコマンドを使用して変数を再構築します

printf組み込みコマンドは文字列フォーマットを描画する強力な方法を与えます。これはBash 組み込みであるため、stdoutに出力する代わりにフォーマットされた文字列を変数に送信するためのオプションがあります。

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

この配列には7つのstringsがあります。それで、ちょうど7つの位置引数を含むフォーマットされた文字列を作ることができます:

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

あるいは、1つの引数フォーマット文字列を使用することもできます。

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の下では、インデックスを指定せずに変数名にアクセスすると、常に最初の要素だけがアドレス指定されます。

7フィールド配列を取得するには、最初の要素を再設定するだけです。

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

多数の引数が1つの引数フォーマット文字列に渡されます。

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

Stack Overflow question構文を使う:

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

forkedprintfを使用してフォーマット

もっと洗練された構造を使いたいのなら、fork(仕事をしてstdoutを通して結果を返す新しい子プロセス)を使わなければなりません:

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

歴史的には、forkの結果を取得するためにbackticksを使うことができました:

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
885
F. Hauri

これもできます。

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh
123
userend
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

出力します

helloohaikthxbye

これは$blaohaiが変数が見つからないというエラーにつながる場合に便利です。文字列にスペースやその他の特殊文字が含まれている場合もあります。 "${foo}"はあなたが入れたものを適切にエスケープします。

115
orkoden
foo="Hello "
foo="$foo World"

41
vinothkr

私が問題を解決する方法はただ

$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
32
Chris Smith
$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop
27
bcosca

これはほとんどの答えが話していることの簡潔な要約です。

2つの変数があるとしましょう。

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行目のように)

また見なさい:

20
codeforester

アンダースコアのようなものを追加したい場合は、エスケープ(\)を使用してください。

FILEPATH=/opt/myfile

これは ではなく work:

echo $FILEPATH_$DATEX

これはうまくいきます:

echo $FILEPATH\\_$DATEX
20
user2800471

さらに別のアプローチ...

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

...そしてさらにもう一つ。

> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
19
Akseli Palén

引用符を使った最も簡単な方法:

B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
15
betontalpfa

引用符なしで連結できます。これが一例です。

$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
15
mariana soffer

+ =演算子が現在許可されていても、2004年に Bash 3.1 に導入されました。

古いバージョンのBashでこの演算子を使ったスクリプトは、運が良ければ "command not found"エラー、あるいは "予期しないトークンに近い構文エラー"で失敗します。

下位互換性を気にする人は、選んだ答えで述べたような、古い標準のBash連結方法を守ってください。

foo="Hello"
foo="$foo World"
echo $foo
> Hello World
14
Louis-Félix

文字列内の変数を展開するために中括弧${}を使用するのが好きです。

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

波括弧は、連続文字列の使用法に適合します。

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

そうでなければfoo = "$fooWorld"を使用してもうまくいきません。

13
Nick Tsai

より安全な方法:

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

スペースを含む文字列はコマンドの一部になることがあります。これらのエラーを避けるために "$ XXX"と "$ {XXX}"を使用してください。

さらに、 + = についての他の答えを見てください。

7
Bohdan

あなたがやろうとしていることが split 文字列を複数の行に分割することであるなら、あなたはバックスラッシュを使うことができます:

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

間にスペースが1つあります。

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

これはまた、間にスペースを1つだけ追加します。

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

気をつけるべき特別なケースが1つあります。

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

あなたが望むかもしれないので、danielsanではなく"daniel"sanを出力します。この場合、代わりにするべきです:

user=daniel
cat > output.file << EOF
${user}san
EOF
6
diogovk

元の文字列に" World"を追加する例としての場合は、次のようになります。

#!/bin/bash

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

出力:

Hello World
var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3
5
hari

パフォーマンスについては大きな懸念がありますが、データは提供されていません。簡単なテストを提案しましょう。

(注:macOSのdateはナノ秒を提供しないので、これはLinux上で行わなければなりません。)

GitHub上に append_test.shを作成しました

#!/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 になったことを示しています。 コードを データを2倍にすることから、より詳細なグラフと失敗点を得るための定数の追加に変更することができます。しかし、これはあなたが気にするかどうかを決定するのに十分な情報をあなたに与えるはずだと思います。個人的には、100 MB未満ではできません。あなたのマイレージは異なる場合があります。

4
Bruno Bronosky
a="Hello,"
a=$a" World!"
echo $a

これは、2つの文字列を連結する方法です。

4
CodeNinjaPI

リストから文字列を作りたかった。答えが見つからなかったので、ここに投稿します。これが私がしたことです:

list=(1 2 3 4 5)
string=''

for Elm in "${list[@]}"; do
    string="${string} ${Elm}"
done

echo ${string}

それから私は次のような出力を得ます:

1 2 3 4 5
4
Simon Bachmann

これは機能しないことに注意してください

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

それは$ fooを落として、あなたを残しているので:

PREFIX_WORLD

しかしこれはうまくいきます:

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

そして正しい出力を残します。

PREFIX_HELLO_WORLD

3
Dss

都合が良いときにこのようにします。インラインコマンドを使用します。

echo "The current time is `date`"
echo "Current User: `echo $USER`"
1
Marty

私の意見では、2つの文字列を連結する最も簡単な方法は、それを行う関数を作成してから、その関数を使用することです。

function concat ()
{
    prefix=$1
    suffix=$2

    echo "${prefix}${suffix}"
}

foo="Super"
bar="man"

concat $foo $bar   # Superman

alien=$(concat $foo $bar)

echo $alien        # Superman
1

これは _ awk _ を介したものです。

$ foo="Hello"
$ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
$ echo $foo
Hello World
1
Avinash Raj