22
#!/bin/sh
for i in {1..5}
do
   echo "Welcome"
done

動作しますが、Welcome が 5 回表示されます。

#!/bin/sh
howmany=`grep -c $1 /root/file`
for i in {1..$howmany}
do
   echo "Welcome"
done

うまくいきません!howmanyの出力が表示されるため、5 に等しくgrep -cなります。$1 は、スクリプトの実行時に固有のパラメーター 1 です。

何か案は?

4

6 に答える 6

24

シーケンス ブレース式で変数を使用できない場合の回避策:

  • OPの場合のように、範囲内の数値を単に反復することが目的である場合、最良の選択はブレース展開を使用せず、代わりにbashのCスタイルループを使用することです-user000001の回答を参照してください。

    • 特定の数が重要ではなく、ループ本体を指定された回数だけ実行する必要がある場合は、Cole Tierney の答えがオプションです。
  • それにもかかわらず、ブレース展開の使用が必要な場合:

    • リスト内の数字に接頭辞または接尾辞を付ける必要がない場合は、引用符で囲まれていないコマンド置換を使用してseqユーティリティを使用します (小さな注意: POSIX ユーティリティではありませんが、広く利用可能です)。例えばseq

      • echo $(seq 3)-> 1 2 3; 開始番号の1 暗示
        • echo $(seq -f '%02.f' 3)-> 01 02 03- ゼロ埋め
      • echo $(seq 2 4)-> 2 3 4; 明示的な開始番号と終了番号
      • echo $(seq 1 2 5)-> 1 3 5; カスタムインクリメント2真ん中)
    • リスト内の数字にプレフィックスまたはポストフィックスが必要な場合は、いくつかの選択肢があります。

      • -style フォーマット文字列 (上記でゼロパディングに使用されているように)を提供するためのオプション、または(特別な注意が必要です!)に基づく純粋な Bash 回避策、またはループで配列seqを構築するためのオプションを指定してユーティリティを使用します。答えてください。-fprintfeval
      • awkまたはなどのユーティリティを使用してカスタム シェル関数またはカスタム スクリプトを作成するなど、機能を一般的に実装することも検討できますperl

evalシーケンス ブレース式を駆動する変数での安全な使用例:

変数は事前に検証され、10 進整数が含まれていることを確認します。

from=1 to=3  # sample values

# Ensure that $from and $to are decimal numbers and abort, if they are not.
(( 10#$from + 10#$to || 1 )) 2>/dev/null || { echo "Need decimal integers" >&2; exit 1; }

eval echo "A{$from..$to}"  # -> 'A1 A2 A3'

ブレース展開の概要

ブレース展開の主な目的は、トークンのリストに展開して、各トークンにオプションのプレフィックスおよび/またはポストフィックスを付けることです。ブレース展開は引用符で囲まれていない必要があり、次の2 つのフレーバーがあります。

  • コンマ区切り文字列の固定系列(リスト) -サポートされる変数
    • 固定数のトークン(2 以上)を指定して展開します。例えば:
    • echo A{b,c,d}-> Ab Ac Ad、つまり、引数の数によって暗示される 3 つのトークン。
    • echo {/,$HOME/}Library例 - >/Library /User/jdoe/Library
    • 変数参照 (さらにはグロブも)サポートされていますが、ブレース展開のに通常の評価の過程で結果として展開されることに注意してください。
  • シーケンス式 (範囲)..通常は数値-変数サポートされていません

    • リテラルの開始点と終了点によって駆動される可変数のトークンに展開されます(歴史的な理由から変数の使用はサポートされていません- user000001 の回答のコメントを参照してください):
      • [まれな]文字列:単一の英字のみが許可されます。例えば{a..c}
      • 数値: 10 進整数のみ。例: {1..10}{10..1}{-1..2}
        • 接頭辞と接尾辞の例: A{1..3}#->A1# A2# A3#
        • 変数を使用した壊れた例: {$from..$to} # !! FAILS- $fromandはリテラル$toとして解釈されるため、1 文字または 10 進整数として認識されません - 中括弧展開は実行されません(以下を参照)。
          • 対照的に、変数の使用zshおよびで機能しkshます。
      • bash 4+には次の 2 つの機能が追加されています。
        • オプションの増分ステップ値:
          • echo A{1..5..2}-> A1 A3 A5- 2 ずつ増加する数値
        • ゼロパディング機能:
          • echo A{001..003}->A001 A002 A003
  • 無効なブレース展開されません(引用符で囲まれていない通常の文字列のように{扱わ}れ、リテラルとして扱われます):

    • echo {}-> '{}'- ブレース式としては無効です: 少なくとも2 つ ,の -区切られたトークンが必要です
      • これにより、たとえばunquoted {}with を使用できます。find
    • echo {1..$to}-> '{1..<value-of-$to>}'- ブレース expr としては無効です。in bash: 変数はサポートされていません。ただし、およびで有効です。kshzsh
    • (fish対照的に、 は任意の {...}シーケンスを展開します。同様に、 には、 内の個々の文字を展開するためのzshオプションBRACE_CCL(デフォルトではオフ) があり、空でないシーケンスの展開を効果的に引き起こします。){..} {...}
于 2015-03-12T22:55:53.323 に答える
9

問題は、「ブレース展開」が「変数展開」の前に実行されることです

for i in $(seq 1 $howmany) 

@damienfrancoisが言ったように機能します。または、必要に応じて:

for i in $(eval echo "{$start..10}") 

おそらくそうですが、みんなの正気のためにそれを使用しないでください。

于 2013-10-17T17:04:16.743 に答える