変数を設定しました。TEMPP='-I ../dir1 -I ../dir2'
だから私は走る
gcc -M $TEMPP somefile.c
含まれているファイルの検索リストに../dir1
含まれていないように見え、../dir2
変数の先頭にスペースがある場合(例:
TEMPP=' -I ../dir1 -I ../dir2'
エラーが報告されます。
gcc: -I ../common1 -I ../encrypt: No such file or directory
だから変数をファイルとして扱うようです。
おそらく、この問題を避けるためにディレクトリを分離することができます。ただし、含まれているディレクトリはdirs
他のコマンドによって生成され、数値は一定ではありません。
それでは、コマンドの変数をリテラルとして処理し、整数文字列やファイル名ではなくコマンドラインから手動入力のように見えるようにするにはどうすればよいですか?
zsh
まあ...これはbashでのみ発生しますが、bashではうまく動作することがわかりました。おそらく、変数zsh
の拡張は特別かもしれません。
だから誰でもzshでこれをうまく機能させる方法を教えてくれたらとても感謝します。それ以外の場合は、bashでのみこれを実行できます。
答え1
"$TEMPP"
私は空白が解釈されるかどうかを制御しようとしていると思います。 (これはGCCの問題ではなく、シェルがコマンドラインを解析する問題です。)
これがbash
すること:
$ F="foo bar baz"
$ for f in $F; do echo $f; done
foo
bar
baz
これがzsh
すること:
$ F="foo bar baz"
$ for f in $F; do echo $f; done
foo bar baz
zsh
スペースを説明する必要があります。 zshでこれを行うエレガントな方法があるかもしれません(わかりませんが、質問のタイトルを変更してタグ付けすると、より便利な答えが得られます)。これは問題を解決しますが、問題に対する負担は少し大きくなります。
eval gcc -M $TEMPP somefile.c
答え2
zshでは、他のBourneスタイルのシェルとは異なり、変数置換の結果はワイルドカードパターンとして解釈される単語に分割されません。したがって、zshで書くと
a='hello *.txt'
echo $a
これにより、hello *.txt
他のシェルとは異なり、次のようなものが表示されますhello bar.txt foo.txt
。
個人用の単語分割を設定できます。拡張そして$=TEMPP
。setopt sh_word_split
すべての拡張子に対して単語区切りを有効または設定できますemulate sh
。
これらのコマンドをmakefileに入れて、真のBourneスタイルシェル(インストールされているすべてのもの/bin/sh
)でそれを実行する必要があります。インタラクティブな使用と独自のスクリプトのためにzshを予約してください。
答え3
可変数の値を保持する変数を配列と呼びます。
var=value
スカラー変数の割り当て構文は次のとおりです。一つ値は a に割り当てられます。スカラー変数。
var=( one two 'three or 3' )
はい配列変数値を割り当てることができる割り当て構文乱数(でも0²)値配列/リスト変数。
var[n]=foo
スカラー割り当て構文でもありますが、割り当ては一つ配列のn番目の要素の値です。
欲しいものは次のとおりです。
extra_options=( -I ../dir1 -I ../dir2 -I '/opt/my software/include' )
gcc -M $extra_options somefile.c
拡張は、$extra_options
配列の空の要素$extra_options
(存在する場合)をスキップ$scalar
します。いいえ空の場合、引数は代わりに空の要素です$scalar
。
"$scalar"
空の要素を保存するには、or "$array[@]"
("${(@)array}"
または"${array[@]}"
bashなどのksh様シェルと互換性があり、"$@"
Bourneシェルを思い出させる)が必要です。
他のBourneに似たシェルでは、次の点に注意してください。
TEMPP='-I ../dir1 -I ../dir2'
gcc -M $TEMPP somefile.c
$TEMPP
暗黙的にいわゆる話すことを体験してください。分割+グローバル$TEMPP
演算子を使用すると(幸いにも!)の値はシェルコードにそのまま含まれているようには見えませんgcc -M -I ../dir1 -I ../dir2 somefile.c
。
ケース 4の場合は次のようになります。
TEMPP='foo>/etc/passwd;reboot' # or '$(reboot>/etc/passwd)'
echo $TEMPP
/etc/passwd
たとえば、上書きして再起動します。変数拡張中は、シェル構文(;
、>
演算子、${...}
拡張子$(...)
、引用符を含む)は認識または処理されません。ただし、zshやその他のより一般的な最新のシェル(rc、es、fish、akanga ...)や他のプログラミング言語のようにそのまま拡張されていませんが、代わりに分割+glob演算子を使用します。
値は$TEMPP
文字のみで分割され、$IFS
ワイルドカードとして表示されます(ファイル名の生成またはパス名拡張とも呼ばれます)。これは次のことを意味します。
TEMPP='-I ../dir1 -I ../dir2'
gcc -M $TEMPP somefile.c
これは行$IFS
を解釈するときに空白文字が含まれている場合にのみ機能し、gcc...
他の文字は含まれません$TEMPP
(幸いにもデフォルトの場合$IFS
)。たとえば、が含まれている場合、および$IFS
パラメータi
をgcc
使用して呼び出されます。-I ../d
r1 -I ../d
r2
そして:
TEMPP='-I ../dir1 -I ../dir2 -I "/opt/my software/include"'
gcc -M $TEMPP somefile.c
シェル構文(引用符など)を解釈せずに分割のみを実行するため、機能しません。$IFS
したがって、スペースを含むパラメータを渡す必要がある場合は、分割に別の区切り文字を使用する必要があります。例:
TEMPP='-I,../dir1,-I,../dir2,-I,/opt/my software/include'
IFS=,
gcc -M $TEMPP somefile.c
例えば。値に*
など?
のワイルドカード演算子が含まれている場合は、拡張する前にコマンドを実行してワイルドカード文字が拡張されないようにする必要が[...]
あります。set -o noglob
また、見ることができますbash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスクBourneに似たシェル(zshを除く)の誤ったデザインがセキュリティに与える影響。
zshで-splittingおよび/またはglobbingが必要な場合$IFS
(ただし、通常は他のほとんどの最新のシェルのようにzshに配列がない)要求する必要があります。明らかに、$=scalar
分割 on は、$IFS
内容$~scalar
を$scalar
パターンとワイルドカード、またはその両方として扱うため、他の Bourne 様シェル$=~scalar
と同じです。$scalar
を使用する代わりに、区切り${(s[whatever])scalar}
文字で分割を参照し、行eed(改行文字とも呼ばれる)またはNULで分割する方法を簡単に参照してください。$IFS
${(f)scalar}
${(0)scalar}
f
zsh
他のBourne型またはKorn型シェル用に書かれたコードを解釈する必要がある場合は、そのコードを使用またはsh
エミュksh
レートできます。ここで、これらのシェルとの互換性は次のように改善されます。
emulate ksh
:シミュレーションを明示的に変更します(デフォルトのemulate zsh
通常モードを復元しますが)。emulate -L ksh
:同じですが、L
ローカルでのみ可能です(たとえば、現在の関数内など)。emulate ksh -c 'ksh/bash code here'
あるいは、emulate ksh -c 'source some-ksh-or-bash-script'
そのシミュレーションモードで与えられたコードを解釈するだけです。
sh または ksh エミュレーションでは、IFS スプリットとワイルドカードの指定は、sh/ksh/bash のようにリストのコンテキストで引用されていない引数拡張時に暗黙的に実行されます (そして、シェルの動作に影響を与える他の多くのshwordsplit
オプションglobsubst
は次のように動作します.するように調整されます。
1set var = ( one two 'three or 3' )
配列を導入した最初のシェルであるcshに触発され、後でset -A var one two 'three or 3'
ksh93(以前のバージョンのkshにもこの機能があったにもかかわらず)、bashやyashなどの他のシェルによってコピーされました。
²注:ksh93は最初に配列を作成するため、var=()
宣言はありません。var
化合物配列変数の代わりに変数。
立方体1つの例外を除いて、zshおよび他のすべてのシェルで:ksh(そしてzshの代わりにkshをコピーするbash)、ここで配列インデックスは0から始まり、配列はスパースなので、インデックス0の要素も設定されると、2番目の要素がすべて割り当てarray[1]=x
られます。array[123]=x
追加設定なしの要素範囲は0〜122です。
実際、これは70年代初頭の最初の(非常にシンプルで原始的な)Unixシェルの場合でした。このシェルには変数もなく、コマンドの置換もありませんでしたが、$1
この$9
ような拡張位置引数がありました。