
POSIX shまたはBourneシェル(Solaris 10のように/bin/sh
)で次のようなものを持つことはできますか?
a='some var with spaces and a special space'
printf "%s\n" $a
そしてデフォルトを使用すると、次のような結果がIFS
得られます。
some
var
with
spaces
and
a
special space
つまり、引用またはエスケープの組み合わせでspecial
間のスペースを保護することです。space
a
辞書に単語数がわからない場合は、次のことを試してください。
a='some var with spaces and a special\ space'
printf "%s\n" "$a" | while read field1 field2 ...
文脈はこのエラーCassandraが報告したように、OPはJVMオプションを指定する環境変数を設定しようとしました。
export JVM_EXTRA_OPTS='-XX:OnOutOfMemoryError="echo oh_no"'
Cassandraを実行するスクリプトはPOSIX shとSolaris shをサポートする必要があります。
JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS"
#...
exec $NUMACTL "$JAVA" $JVM_OPTS $cassandra_parms -cp "$CLASSPATH" $props "$class"
IMOの唯一の方法は、コマンドをラップするスクリプトを使用することですecho oh_no
。別の方法がありますか?
答え1
まさか。
1つの解決策は、文字をフィールド区切り文字として予約することです。当然、そのキャラクターが何でもオプションに含まれる可能性は低いです。ソース言語がタブと改行文字を簡単に挿入できる場合、これは確かな候補です。移植性が必要な場合は、マルチバイト文字を使用しないでください(たとえば、ダッシュとBusyBoxはマルチバイト文字をサポートしていません)。
IFS分割に依存する場合は、ワイルドカード拡張をオフにすることを忘れないでくださいset -f
。
tab=$(printf '\t')
IFS=$tab
set -f
exec java $JVM_EXTRA_OPTS …
別のアプローチは、参照構文を導入することです。非常に一般的な引用構文は、バックスラッシュを使用して次の文字を保護することです。バックスラッシュの使用の欠点は、さまざまなツールでバックスラッシュを引用符として使用し、時には必要なバックスラッシュの数を決定するのが難しいことです。
set java
eval 'set -- "$@"' $(printf '%s\n' "$JVM_EXTRA_OPTS" | sed -e 's/[^ ]/\\&/g' -e 's/\\\\/\\/g') …
exec "$@"
答え2
Bashなどを使用している場合、配列はトリックを実行します。
a=(some var with spaces and a 'special space')
しかし、POSIXシェルにはこれらの機能がないので、私が見ることができる最良の内部アプローチは実際に特別なスペースを使うことです。切り捨て防止スペース(U + 00A0)はこの目的に適していますが、ASCII以外ではスクリプトの文字セットに同意する必要があります。
a="some var with spaces and a special space"
# this is a non-breaking space ------^
echo "$a" \
| while read word; do printf '%s\n' ${word} | sed 's@ @ @g'; done
# this is a non-breaking space ----------------------^
この出力は次のようになります。
some
var
with
spaces
and
a
special space
現時点では、これを変数拡張にどのように含めるべきかわかりません(サブシェルが必要です)。しかし、これはさらなる調査のための出発点になります。