bash - 追加 - シェルスクリプト 文字列 連結 ループ




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

バッシュを最初に

この質問はBashに特化しているので、私の答えの最初の部分はこれを正しく行う様々な方法を提示します:

+= :変数に追加

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

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

(私は倹約的なので、私は2つの変数fooaを使い、答え全体で同じ変数を再利用します;-)

a=2
a+=4
echo $a
24

スタックオーバーフローの質問構文を使用して、

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

正常に動作します!

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

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

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

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

私たちはまた、ただ一つの要素の配列です。

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つの文字列があります。 したがって、正確に7つの位置引数を含む書式設定された文字列を作成できます。

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

したがって、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!>

スタックオーバーフローの質問構文の使用:

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

注意: 二重引用符を使用すると、 spacestabulationsおよび/またはnewlinesを含む文字列を操作するのに便利です

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

今すぐシェル

POSIXシェルの下では、 bashismsを使うことができなかったので、 printf組み込まれていません。

基本的に

しかし、あなたは単に行うことができます:

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

フォークされた printfを使用して書式設定されました

より洗練された構造を使いたい場合は、 fork (新しい子プロセスでジョブを作成し、 stdout結果を返す)を使用する必要があります:

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

歴史的には、 フォークの結果を取得するためにバッククォートを使用することができます。

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

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

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

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

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


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

古いBashバージョンでこの演算子を使用しているスクリプトは、あなたが運が良ければ "コマンドが見つかりません"というエラー、または予期しないトークンに近い構文エラーで失敗します。

下位互換性を気にする人は、選択した答えに書かれているような古い標準のBash連結メソッドを使用してください。

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

PHPについてはまだ分かりませんが、これはLinux Bashで動作します。 変数に影響を与えたくない場合は、これを試すことができます:

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

>Hello World!

'Hello'や '!'の代わりに別の変数を置くこともできます。 より多くの文字列を連結することもできます。


あなたは以下の方法で試すことができます。 置換が行われると、二重引用符でスペースが保持されます。

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

ここでは、ほとんどの答えが何を話しているのかを簡潔にまとめたものです。

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

参照:


ここにAWKを通したものがあります:

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

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

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

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

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

より安全な方法:

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

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

プラス+についての他の答えを見て+


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

(注: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達したことを示しています。 コードを変更し 、データを倍増させて定数を追加することで、より細かいグラフと障害ポイントを得ることができます。 しかし、これは、あなたが気にしているかどうかを判断するのに十分な情報を与えるはずです。 個人的には、100 MB未満ではありません。 あなたのマイレージは異なる場合があります。


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

#!/bin/bash

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

出力:

Hello World

引用符を使用する最も簡単な方法は次のとおりです。

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

文字列を複数の行に分割する場合は、バックスラッシュを使用できます。

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

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

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

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

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

注意が必要な特別なケースが1つあります。

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

あなたが望むかもしれないように、 "daniel"sanではなく、 "daniel"san出力します。 この場合は、代わりに以下を実行する必要があります。

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

私が問題を解決する方法はちょうど

$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

私は便利なときにこのようにします:インラインコマンドを使用してください!

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

私は素早く機能するようなものです。

#! /bin/sh -f
function combo() {
    echo [email protected]
}

echo $(combo 'foo''bar')

猫を肌にさらすもう一つの方法。 関数を使って今回は:D


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

出力する

helloohaikthxbye

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


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


var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3




string-concatenation