web-dev-qa-db-ja.com

最後のコマンドをN回繰り返す

ループを書くのではなく、最後のコマンドをN回繰り返す方法はありますか?.

たとえば、ダブルバン(!!)を使用して最後のコマンドを1回繰り返すことができますが、30回言うにはどうすればよいですか。

7
Tyler Durden

zshを使用し、最後のコマンドラインが1つのコマンドまたはパイプラインまたはand-orリスト(つまり、echo xecho x | tr x yecho x && echo y、さらには複合{ x; y; }またはfor/whileのようなコマンドはループしますが、echo x; echo yはループしません):

repeat 30 !!

複数のコマンドが含まれている場合でも、前のコマンドラインを繰り返すには、次のコマンドを使用します。

repeat 30 do !!; done

または:

repeat 30 {!!}

bashを使用して、単純なコマンドのみ(上記の例の中でecho xの場合のみ)の場合、次のようなヘルパー関数を定義できます。

repeat() {
  local n="$1"
  shift
  while ((n-- > 0)); do
    "$@"
  done
}

(そして上記のようにrepeat 30 !!を使用してください)。副作用は、コードが関数で実行されるため、異なる"$@""$#"が表示され、typesetなどの動作が異なるため、実行できないことです。お気に入り:

eval 'echo "$1"'
repeat 30 !!

zshrepeat 30 {!!}をエミュレートする別の方法は、次のようなエイリアスを宣言することです。

alias repeat='for i in $(seq'

(未変更の$IFSと想定)

次に使用します:

repeat 30); { !!; }
9

私が思いつくことができる最短のものは:

date # or whatever command
for i in {1..30}; do !!; done
8
Jeff Schaller

1つの方法は、ラインエディターを使用して!!;を30回挿入することです。

readlineモードのbashviの行エディター)と同様:

!!;Escdd30p

同等のemacsモードはzsh行エディターでは機能しますが、bashreadlineでは機能しないようです。ただし、代わりにreadline kbdマクロを使用することもできます。

Kbdマクロを!!;として定義します。

Ctrl+X(!!;Ctrl+X

後で30回呼び出すことができます。

Alt+3Alt+0Ctrl+Xe
3

これは少し見苦しいですが、

 eval "`fc -ln -1`;: "{1..10}\;

先頭のスペースは厳密には必要ありませんが、evalコマンドを履歴に入力しないようにするには、$HISTCONTROLにはignorespace(またはignoreboth)が含まれています。

または:

eval "fc -s $((HISTCMD-2)) "{1..10}\;

そして:

eval 'history -s '{1..10}';fc -s -2;'
1
ecatmur

Bashの別のループ(この後: https://unix.stackexchange.com/a/372​​487/9689

$PATHrepeatという名前の実行可能ファイルにして、zshと同様の効果を実現します( https://unix.stackexchange.com/a/372​​484/9689 ):

#!/bin/bash

n=$1
shift 1

for ((x=0; x<$n; ++x)); do
  "$@"
done

後でできること:

$ repeat 3 date

要旨: https://Gist.github.com/gwpl/26fefe3a165304f3dedb21009506107f

seqコマンドは標準の* nixの一部であるため、シェルに依存しません。それとシェルのループ構造を使用すると、次のようなことができます。

for i in $(seq 30); do !!; done

または

for i in `seq 30`; do !!; done

0
AlwaysLearning