
私は次のことを行います。
$ ./input ""
出力:
argc 2
argv[1][0] 0
ただし、プログラムベースの方法で(複数の)空の引用符を渡したい場合:
$ python -c 'print "\"\""'
""
./input $(python -c 'print "\"\""')
以下を提供します。
argc 2
argv[1][0] 22 - (22 hex value for ")
では、どうすれば次のようなものを生成できますか?
$ ./input "" "" "" ""
例1と同じ結果が得られますか?
答え1
存在する
./input $(cmd)
$(cmd)
引用符で囲まないのは、分割+グローブ演算子であるからです。シェルによって取得された出力は、末尾の改行をcmd
すべて削除し、特殊引数の値$IFS
に従って分割し、生成された*.txt
単語(現在のディレクトリに隠されていないtxtファイルのリストなど)を使用してファイル名を生成します(なし後半)、zsh
の場合は中ksh
括弧の拡張(たとえば、a{b,c}
行ab
、および)も実行します。ac
デフォルトには$IFS
SPC、TAB、およびNL文字が含まれます(zsh
他のシェルはNULを削除または終了します)。これら(NULではない)はIFS空白文字でもあり、IFS分割中に特に処理されます。
Split+glob 演算子は、 の出力がで引数があればcmd
生成されます。 IFS空白文字の場合、1つ以上のIFS空白文字シーケンスが考慮されているため、空の引数を生成できません。" a b\nc \n"
"a"
"b"
"c"
./input
split+glob
一つ分離記号。空のパラメーターを生成するには、IFS 空白文字ではなく区切り文字を選択する必要があります。実際、空白以外の文字はすべて可能です(すべてのシェルがサポートしているわけではありませんが、マルチバイト文字を避けるのが最善です)。
たとえば、次のような場合:
IFS=: # split on ":" which is not an IFS-whitespace character
set -o noglob # disable globbing (also brace expansion in ksh)
./input $(cmd)
cmd
出力の場合、a::b\n
分割+glob演算子は引数を生成します"a"
(""
s"b"
は"
値の一部ではなく、ここでは値を表示するのに役立つように使用しています)。
の場合、a:b:\n
シェルに応じてand"a"
または、andになります。次のコマンドを使用して、すべてのシェルで一貫性を維持できます。"b"
"a"
"b"
""
./input $(cmd)""
(これは空の出力cmd
(または改行のみを含む出力)の場合、引数が./input
まったくない代わりに空の引数が受け取られるという意味でもあります。
例:
cmd() {
printf 'a b:: c\n'
}
input() {
printf 'I got %d arguments:\n' "$#"
[ "$#" -eq 0 ] || printf ' - <%s>\n' "$@"
}
IFS=:
set -o noglob
input $(cmd)
以下を提供します。
I got 3 arguments:
- <a b>
- <>
- < c>
また、これを行うときは、次の点に注意してください。
./input ""
これは"
シェル構文の一部であり、シェル引用演算子です。これらの"
文字はに渡されませんinput
。
^IFS スペース文字、各POSIXはロケールに分類された文字であり、ksh88(POSIX仕様のベース)とほとんどのシェルで発生する[:space:]
ように、これはまだSPC、TAB、およびNLに制限されています。$IFS
これに関して私が見つけた唯一のPOSIX互換シェルはですyash
。ksh93
(bash
5.0ベース)他のスペース(CR、FF、VTなど)も含まれていますが、シングルバイトスペースに制限されています(たとえば、Solaris)(一部の領域にはシングルバイトの切り捨て防止スペースが含まれています)
答え2
プログラムでコマンドライン全体を作成し、コピーして貼り付けるか、evalを介して実行できます。たとえば、次のようになります。
$ perl -e 'printf "./args.sh %s\n", q/"" / x 10'
./args.sh "" "" "" "" "" "" "" "" "" ""
$ eval "$(perl -e 'printf "./args.sh %s\n", q/"" / x 100')"
$#: 100
$1: ><
(これは何百ものコピーを作成してリンクしてq/"" /
Perlが文字列を引用する方法の1つです。)x 100
eval
その引数をシェルコマンドで処理して、すべての引用符の処理と拡張を実行します。これは、入力が信頼できないソースから来る場合、脆弱性を防ぐために評価コードを生成するときに注意する必要があることを意味します。
空の引数変数の数が必要な場合は問題ありません。 (少なくともPerlの2番目のオペランドがx
オペランドを整数に縮小するため、どのように誤って使用できるかはわかりません。)
$ n=33
$ eval "$(perl -e 'printf "./args.sh %s\n", q/"" / x $ARGV[0]' "$n")"
$#: 33
$1: ><
答え3
しかし、実際に何を克服しようとしていますか?空引用符または空ひも?どちらも有効なパラメータです。この単純なbashスクリプトはこれを説明するのに役立ちます。
#!/bin/bash
printf "Argument count: %s.\n" "${#@}"
渡された引数の数だけを印刷します。s
便宜上と呼びます。
$ ./s a
Argument count: 1.
$ ./s a b
Argument count: 2.
$ ./s a b ""
Argument count: 3.
$ ./s a b "" ""
Argument count: 4.
$ ./s a b "" "" \"\"
Argument count: 5.
ご覧のとおり、空の文字列は空の文字列だけです。構文解析時に引用符が削除され、まだ有効な引数です。シェルはこれをコマンドに入力します。しかし""
それはまた伝達されるかもしれない。しかし、空の文字列ではありません。 2つの文字が含まれています。
内部的には、Cでは文字列がNUL(\0
)で終わり、文字列を表示するために引用符は必要ありません。