パターンを介してパラメータを解析しようとしていますrecursive descent
。
これらの文は、各実行後に次の手順を実行するためにwhile
関数を呼び出します。eat!
$current_token
今問題は無限ループに入ることです。
正確に言えば、関数には2つのwhileループがあります。
複合語が文法的(または論理的に?)間違っているため、どちらか一方または両方が機能しません。
さまざまなレベルで発生する可能性のある問題について、次のコードを確認してください。
1)
while $(isWord? $current_token) || ! $(isVersionNumber? $current_token) && ! $(endOfInput?); do
while isVersionNumber? $current_token && ! endOfInput?; do
また何が正しいですか?コマンドの置き換えにチェック機能を追加しますか?
短絡によりendOfInput?
テストも防止できませんか?
なぜなら、それは明らかにサイクルを停止しなければならないからです。
イルカチュウのお願いで
テスト機能コード:
isWord? () {
local pattern="^[a-zA-Z0-9_-]+$"
if [[ $1 =~ $pattern ]]; then
echo true
else
echo false
fi
}
isVersionNumber? () {
local pattern="^[0-9]{1,2}(\.[0-9]{,2})*$"
if [[ $1 =~ $pattern ]]; then
echo true
else
echo false
fi
}
EO_ARGS=1
function endOfInput? {
if [ $current_token_index -ge $ARGC ]; then
EO_ARGS=0
fi
echo $EO_ARGS
}
コマンドの置き換えに使用しているので、別のコマンドを出力するとしますか?
いいえ、コマンド置換を使用せずに条件付きで関数を呼び出すことが可能かどうかわからないため、これは単なる試みです。
eat!
完璧にするために、この機能も追加しました。
eat! () {
if [[ ! $(($current_char_index + 1)) -gt $ARGC ]]; then
current_token=${ARGV[$current_token_index]}
((current_token_index += 1))
current_char=${current_token:0:1}
}
test
/ [
()を使用すると、条件を[[
よりよく表現できますか?
感嘆符は失敗ポイントになることができますか?
以下は構文上間違っているようです。
while [ endOfInput -eq 1 ] && isWord? "$current_token" || ! isVersionNumber? "$current_token"; do
括弧で[
エラーメッセージが表示されます。
[: endOfInput: integral expression expected (translation)
答え1
関数がtrueの場合は0を返し、falseの場合は別の値を返す場合は直接使用できます。
my-true () {
return 0
}
while my-true ; do
echo Infinite loop...
done
false は何も出力しませんが、 true は何かを出力する場合はコマンド置換を使用します。
my-true () {
echo OK
}
while [ "$(my-true)" ] ; do
echo Infinite loop...
done
前者の場合、関数を連結するには、&&
演算子||
を使用できます。
while func1 && func2 ; do
後者の場合は、代わりに接続を使用できます||
。
while [ "$(func1 ; func2)" ] && [ "$(func3)" ]
後者の場合、サブシェルから呼び出されるため、関数のグローバル変数を変更することはできません。
ただし、関数名に使用することは?
禁止されていませんが、ワイルドカードなので問題が発生する可能性があります。
abc? () {
return $1
}
abc? 0 # Everything OK.
touch abcX
abc? 0 # line 9: ./abcX: Permission denied
abc\? 0 # This works, but where's the charm?
!
デフォルトの歴史的拡張文字ですが、主に対話型シェルにのみ関連しています。
答え2
さまざまなレベルで発生する可能性のある問題について、次のコードを確認してください。
いいね
また何が正しいですか?コマンドの置き換えにチェック機能を追加しますか?
コマンド置換は内部コマンドを使用します。印刷、コマンドラインに入力します。 (分割とグローブ後に拡張が引用されていない場合)
foo() {
echo true
}
if $(foo); then
echo hello
fi
その後、コマンド置換が生成され、true
ステートメントの条件付き部分で実行され、その終了if
状態を使用してデフォルトのブランチが実行されたことを確認しますif
。この場合はそうです。
しかし、これは愚かなことです。コマンドの置き換え(Bashではフォークを含む)を介さずに直接終了状態を返すことができます。
foo() {
return 0
}
if foo; then
echo hello
fi
true
あるいは、最後のコマンドの終了状態が関数の終了状態として使用されるため、end関数を使用できます。
したがって、次のように書くことができます。
isWord? () {
local pattern="^[a-zA-Z0-9_-]+$"
if [[ $1 =~ $pattern ]]; then
return 0
else
return 1
fi
}
while isWord? "$current_token"
でも:
isWord? () {
local pattern="^[a-zA-Z0-9_-]+$"
[[ $1 =~ $pattern ]]
}
while isWord? "$current_token"
すべての一般的な理由(トークン化やワイルドカードなど)のため、この変数を引用する必要があります。
while $(isWord? $current_token) || ! $(isVersionNumber? $current_token) && ! $(endOfInput?); do
ここでa || b && c
構成グループは(a || b) && c
、つまり左から右に実行されることに注意してください。実際のプログラミング言語とは異なりそして演算子より優先順位が高いです。または(つまり、そのa || (b && c)
逆になります)。だから何が必要かを確認してください。
また、Bashのデフォルト設定を使用している間、このような名前はisWord?
頻繁に問題にならないかもしれませんが、まだglobです。現在のディレクトリに一致するファイルが1つ以上ある場合は、そのファイル名に展開されます。代わりにまたはfailglob
を使用するとnullglob
影響を受けます。例えばfailglob
:
$ foo? () { echo hi; }
$ foo?
bash: no match: foo?
$ "foo?"
hi
グローバルに表示されないように参照する必要があります。 Zshでは、一致しないglobがデフォルトで失敗します。
関数名の最後の文字である感嘆符は重要ではありません。名前の先頭または途中にある場合、シェルで履歴拡張が有効になっていると、履歴拡張が発生する可能性があります(対話式シェルはデフォルトではこれを行いますが、スクリプトはそうではありません)。
段落のためにendOfInput? - テストも防止されませんか?
そんなことがあればwhile bar && ! endOfInput?; do
そうです。bar
左が false 状態を返した場合、結果は次のようになります。そして知られており、右にスキップします。同様に、for||
とtrueが返されます。これが&&
完了しました||
。
しかし、質問には何の文脈も提供しませんでした。つまり、関数を呼び出さないことが重要な理由を説明していないので、これを行うより良い方法を考えることは困難です。