なぜこれが起こるのか教えてください。
Linux bashシェルでは:
ps
PID TTY TIME CMD
20406 pts/0 00:00:01 bash
26896 pts/0 00:00:00 ps
次のコマンドを実行します。
str="a b c d"
printf "%s\n" ` echo $str `
a
b
c
d
しかし、bashスクリプトでは
#!/bin/bash
.
.
.
.
str="a b c d"
printf "%s\n" ` echo $str `
次のように印刷されます。
a b c d
そして、スクリプトの予想結果は次のようになります。
a
b
c
d
私のBashスクリプトで何を見逃していますか? bash ENVやこれに似たものかもしれません。
また、shopt
bashスクリプトでコマンドを実行しましたが、結果は次のようになります。
utocd off
cdable_vars off
cdspell off
checkhash off
checkjobs off
checkwinsize off
cmdhist on
compat31 off
compat32 off
compat40 off
compat41 off
direxpand off
dirspell off
dotglob off
execfail off
expand_aliases off
extdebug off
extglob off
extquote on
failglob off
force_fignore on
globstar off
gnu_errfmt off
histappend off
histreedit off
histverify off
hostcomplete on
huponexit off
interactive_comments on
lastpipe off
lithist off
login_shell off
mailwarn off
no_empty_cmd_completion off
nocaseglob off
nocasematch off
nullglob off
progcomp on
promptvars on
restricted_shell off
shift_verbose off
sourcepath on
xpg_echo off
ベストアンサー1
この動作は、2 つの状況でのみ再現できます。
二重引用符コマンドの置換:
#!/bin/bash str="a b c d" printf "%s\n" "`echo $str`"
または、内部フィールド区切り記号(
IFS
変数)を変更します。たとえば、次のようになります。#!/bin/bash IFS=, str="a b c d" printf "%s\n" `echo $str`
どちらの場合も、出力は次のようになります。
$ ./test.sh
a b c d
最初のケースを変更するには、引用符を削除して復元するには、IFS
コマンド置換の上のデフォルト値に設定します。
IFS=$' \t\n'
IFS
変更後に出力が変わる理由と二重引用符の共通点が何であるかを少し説明してください。
最後から始めましょう。
printf "%s\n" a b c d
とは大きく違う
printf "%s\n" 'a b c d'
最初のケースでは、4つの別々の単語があり、printf
それを1つずつ出力して新しい行を追加します。第2のケースでは、単語全体がa b c d
単一の単語として扱われ、printf
端末に直接出力される。二重引用符を追加すると、出力が単一の単語`echo $str`
として扱われることが明らかになりました。
今IFS
それが始まる場所です。つまり、拡張後に単語を分割するためにttが使用されるため、デフォルトでは式は出力ですが、明示IFS=$' \t\n'
的な引用符を使用しなくても - 世界になります。変数なしでこれをより明確に確認できます。echo a b c d
a b c d
IFS=,
'a b c d'
$ IFS=,
$ printf "%s\n" `echo a b c d`
a b c d
$ IFS=$' \t\n'
$ printf "%s\n" `echo a b c d`
a
b
c
d
$()
最後の注意:バックティックの代わりにコマンド置換形式を使用する方が良いですが、これは別のトピックです。