Что быстрее? если не х в ИЛИ, если х не в [дубликате]

Один очень надежный способ справиться с сопроцессами в Bash состоит в том, чтобы использовать ... coproc встроенный.

Предположим, у вас есть сценарий или функция с именем banana, которые вы хотите запустить в фоновом режиме, захватить все свои результаты, выполняя некоторые stuff и ждать, пока это не будет сделано. Я сделаю симуляцию с этим:

banana() {
    for i in {1..4}; do
        echo "gorilla eats banana $i"
        sleep 1
    done
    echo "gorilla says thank you for the delicious bananas"
}

stuff() {
    echo "I'm doing this stuff"
    sleep 1
    echo "I'm doing that stuff"
    sleep 1
    echo "I'm done doing my stuff."
}

Затем вы запустите banana с помощью coproc так:

coproc bananafd { banana; }

это похоже на запуск banana &, но со следующими дополнительными функциями: он создает два дескриптора файла, которые находятся в массиве bananafd (по индексу 0 для вывода и индекс 1 для ввода). Вы будете записывать вывод banana с помощью read builtin:

IFS= read -r -d '' -u "${bananafd[0]}" banana_output

Попробуйте:

#!/bin/bash

banana() {
    for i in {1..4}; do
        echo "gorilla eats banana $i"
        sleep 1
    done
    echo "gorilla says thank you for the delicious bananas"
}

stuff() {
    echo "I'm doing this stuff"
    sleep 1
    echo "I'm doing that stuff"
    sleep 1
    echo "I'm done doing my stuff."
}

coproc bananafd { banana; }

stuff

IFS= read -r -d '' -u "${bananafd[0]}" banana_output

echo "$banana_output"

Предостережение: вы должны выполнить stuff до banana заканчивается! если горилла быстрее вас:

#!/bin/bash

banana() {
    for i in {1..4}; do
        echo "gorilla eats banana $i"
    done
    echo "gorilla says thank you for the delicious bananas"
}

stuff() {
    echo "I'm doing this stuff"
    sleep 1
    echo "I'm doing that stuff"
    sleep 1
    echo "I'm done doing my stuff."
}

coproc bananafd { banana; }

stuff

IFS= read -r -d '' -u "${bananafd[0]}" banana_output

echo "$banana_output"

В этом случае вы получите ошибку, подобную этой:

./banana: line 22: read: : invalid file descriptor specification

Вы можете проверить, слишком ли поздно ( т.е. если вы слишком долго выполняете свой stuff), потому что после выполнения coproc bash удаляет значения в массиве bananafd, и поэтому мы получили предыдущую ошибку.

#!/bin/bash

banana() {
    for i in {1..4}; do
        echo "gorilla eats banana $i"
    done
    echo "gorilla says thank you for the delicious bananas"
}

stuff() {
    echo "I'm doing this stuff"
    sleep 1
    echo "I'm doing that stuff"
    sleep 1
    echo "I'm done doing my stuff."
}

coproc bananafd { banana; }

stuff

if [[ -n ${bananafd[@]} ]]; then
    IFS= read -r -d '' -u "${bananafd[0]}" banana_output
    echo "$banana_output"
else
    echo "oh no, I took too long doing my stuff..."
fi

Наконец, если вы действительно не хотите пропустить какие-либо движения горилл, даже если вы слишком долго заработаете для своего stuff, вы можете скопировать дескриптор файла banana в другой fd, 3 для например, сделайте свой материал, а затем прочитайте из 3:

#!/bin/bash

banana() {
    for i in {1..4}; do
        echo "gorilla eats banana $i"
        sleep 1
    done
    echo "gorilla says thank you for the delicious bananas"
}

stuff() {
    echo "I'm doing this stuff"
    sleep 1
    echo "I'm doing that stuff"
    sleep 1
    echo "I'm done doing my stuff."
}

coproc bananafd { banana; }

# Copy file descriptor banana[0] to 3
exec 3>&${bananafd[0]}

stuff

IFS= read -d '' -u 3 output
echo "$output"

Это будет работать очень хорошо! последний read также будет играть роль wait, так что output будет содержать полный вывод banana.

Это было замечательно: никаких временных файлов для обработки (баш-ручки все тихо) и 100% чистый баш!

Надеюсь, что это поможет!

-3
задан serv-inc 1 March 2019 в 10:22
поделиться

2 ответа

Это точно так же, разницы нет вообще. Стандартным оператором фактически является not in (см. документы ), форма not 7 in автоматически преобразуется в 7 not in.

Таким образом, рекомендуемый способ - if 7 not in [5, 6, 7], это прямое использование оператора, а также улучшенная читаемость.

0
ответ дан Óscar López 1 March 2019 в 10:22
поделиться

Они абсолютно одинаковы и, следовательно, занимают одинаковое количество времени. not in это просто синтаксический сахар. Используя модуль dis, мы можем видеть, что оба результата приводят к одному и тому же байт-коду:

>>> dis.dis("not x in y")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_NAME                1 (y)
              4 COMPARE_OP               7 (not in)
              6 RETURN_VALUE
>>> dis.dis("x not in y")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_NAME                1 (y)
              4 COMPARE_OP               7 (not in)
              6 RETURN_VALUE

Даже добавление скобок в качестве not (x in y) не меняет этого, если, конечно, вы не добавите больше в скобки :

>>> dis.dis("not (x in y)")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_NAME                1 (y)
              4 COMPARE_OP               7 (not in)
              6 RETURN_VALUE
>>> dis.dis("not (x in y or z)")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_NAME                1 (y)
              4 COMPARE_OP               6 (in)
              6 JUMP_IF_TRUE_OR_POP     10
              8 LOAD_NAME                2 (z)
        >>   10 UNARY_NOT
             12 RETURN_VALUE

Протестировано с Python 3.6.7 и 2.7.15.

0
ответ дан tobias_k 1 March 2019 в 10:22
поделиться
Другие вопросы по тегам:

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