bash - 追加 - シェルスクリプト 文字列 連結 ループ
Bashで文字列変数を連結する方法 (19)
バッシュを最初に
この質問はBashに特化しているので、私の答えの最初の部分はこれを正しく行う様々な方法を提示します:
+=
:変数に追加
構文+=
はさまざまな方法で使用できます。
文字列var+=...
追加する
(私は倹約的なので、私は2つの変数foo
とa
を使い、答え全体で同じ変数を再利用します;-)
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
注意: 二重引用符を使用すると、 spaces
、 tabulations
および/または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
下の表はa
とb
値を組み合わせて新しい変数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