Как бесконечно зацикливать числа в bash?

  1. Как запустить infinite_number_loop в bash? , как показано ниже:

     для i в выражении infinite_number_statement
    do date +% Y-% m-% d -d "$ i день назад" 2> & 1> / dev / null
    если [$? -ne 0]
    затем эхо $ i
    фи
    Выполнено
    
  2. Если я запустил этот цикл в терминале на моем локальном компьютере, возникнут ли проблемы? (Я пробовал использовать большой диапазон случайных чисел с помощью для цикла и однажды завис.)

-1
01.03.2017, 04:30
2 ответа

Не бесконечный цикл, но лучший способ найти фактический предел даты:

#!/bin/bash

j=$((1<<61))
i=0
while ((j>0)); do
    if date +'%Y-%m-%d' -d "$((i+j)) days ago" >/dev/null 2>&1; then
    ((i+=j)) ; # printf 'running i %d 0x%x\n' "$i"{,}
    else
    ((j>>=1)); # printf 'new     j %d 0x%x\n' "$j"{,}
    fi
    ((k++))
    # ((k%10)) || printf 'still running %d 0x%x %d %d' "$i"{,} "$j" "$k"
done
printf "final value of limit %d 0x%x in %d loops\n" "$i"{,} "$k"

Таким образом, предел даты будет:

final value of limit 2147483649 0x80000001 in 64 loops

Удалите символ комментария # , чтобы увидеть, как это делается.

Это не 32-битное число.

Это похоже на 32-битное число:

$ printf '%d\n%d\n' "$(( (1<<31) + 1 ))" "0x80000001"
2147483649
2147483649

Фактически, это 2 ** 31 + номер дня месяца.
Если мы попробуем с последним днем ​​декабря (измените строку 5 в сценарии выше):

date +'%Y-%m-%d' -d "2017-12-31 $((i+j)) days ago"

Мы получим:

final value of limit 2147483679 0x8000001f in 68 loops

Это 31 выше 2 ** 31 :

$ printf '%d\n%d\n' "$(( (2**31) + 31 ))" "0x8000001f"
2147483679
2147483679

Это также зависит от часового пояса.

Арифметические примечания

Максимальное значение для целого числа оболочки - i меньше 2, увеличенное до 63:

$ echo $(( (2**63) - 1 ))
9223372036854775807

Мы можем получить десятичное и шестнадцатеричное представление следующим образом:

$ printf '%d %x\n' "$(( (2**63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff

Это максимальное число, представимое в виде целого числа со знаком 64 бита (если ваша система, конечно, 64 бита). Следующее число (просто добавьте один) будет обернуто (переполнено) до отрицательного числа:

$ echo $(( (2**63) ))
-9223372036854775808

$ printf '%d %x\n' "$(( (2**63) ))"{,} 
-9223372036854775808 8000000000000000

Это самое отрицательное число для 64-битного целого числа со знаком.

Но более быстрый способ получить тот же результат - использовать сдвиг влево, который делает то же самое, что и умножение числа на два:

$ printf '%d %x\n' "$(( (1<<63) - 1 ))"{,}
9223372036854775807 7fffffffffffffff
1
28.01.2020, 05:07

Как запустить infinite_number_loop в bash?

Простой способ: while:; do ... done :

let i=0
while :; do
    let i++
    date +%Y-%m-%d -d "$i day ago" >/dev/null 2>&1 || { echo $i && exit 1; }
done

Если я запустил этот цикл в терминале на моем локальном компьютере, возникнут ли какие-нибудь проблемы?

Нет, пока вы не поймете, что потратили на это слишком много времени.

3
28.01.2020, 05:07

Теги

Похожие вопросы