Назад | Перейти на главную страницу

Запустите многострочный сценарий bash, передаваемый из стандартного ввода

Я ищу простой способ включить в документацию многострочные скрипты, чтобы сделать прозрачным то, что делает каждый шаг.

Это работает

echo "echo 1234" | bash

Так делает это

echo 'for N in 1 2 3; do echo $N; done' | bash

Однако я бы хотел использовать что-то вроде этого (что не работает):

echo <<EOF | bash
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

Обновить, ближайшее рабочее решение на данный момент:

cat <<EOF|bash
for N in 1 2 3 4; do
    echo "N is now \$N"
done
EOF

Хотя в идеале я бы не хотел убегать \$N

Правильное решение не будет:

В идеале это то, что читатель может скопировать, вставить, нажать клавишу ВВОД и выполнить без дальнейших действий.

Думаю, лучшее, что вы можете сделать, это что-то вроде этого:

bash -c '
    echo "Simple scriptlike thingy"
    for I in 1 2 3 45; do
      echo "I is now ${I}"
    done
'

Обратите внимание, что это по существу дает скрипт while в качестве параметра для -c switch, и сам этот параметр будет проанализирован bash. Вот почему вы не можете использовать " знаки вроде этого:

bash -c "
    THING=text
    echo this will not work: $THING
"

потому что в параметре $THING заменяется перед передачей в качестве аргумента, и поскольку THING не установлен, он будет заменен пустой строкой. Строка, заключенная в апострофы, не анализируется, поэтому ее можно использовать для хранения переменных, которые должны быть установлены, когда «второй процесс bash» анализирует скрипт.

Я думаю, что для более сложных сценариев лучше всего было бы попросить ваших читателей сохранить сценарий и запустить его, но для простых конструкций вышеуказанное должно работать.

Если вы процитируете или экранируете разделитель здесь-документа (т.е. <<'EOF' или <<\EOFвместо просто <<EOF), оболочка не будет расширять содержимое (переменных и т. д.).

cat <<'EOF' | bash
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

Кстати, cat команда на самом деле не делает здесь ничего полезного (это то, что известно как "бесполезное использование кошки" или UUoC). Вы можете удалить его и отправить ввод прямо в bash:

bash <<'EOF'
for N in 1 2 3; do
echo "N is ${N}"
done
EOF

Если фрагменту нужно прочитать ввод, это немного сложно, потому что вводом сценария является ... сам фрагмент сценария. В большинстве unix-подобных ОС этого можно избежать, передав скрипт через другой файловый дескриптор и указав bash чтобы «выполнить» этот файловый дескриптор:

bash /dev/fd/3 3<<'EOF'
read -p "Enter something here: " input
echo "You entered: ${input}"
EOF

Но обратите внимание, что любые переменные, установленные в одном из этих фрагментов (например, $input здесь) устанавливаются только в этом одном процессе оболочки и будут потеряны при выходе.