У меня есть следующий код скрипта:

test.sh

echo "BEGIN"
while read CMD <&1; do
    [ -z "$CMD" ] && continue
    case "$CMD" in
    start)
            echo "get_start"
            ;;
    stop)
            echo "get_stop"
            ;;
    *)
            echo "get_uknown_command"
            ;;
    esac
    echo "END";
done

Когда я запускаю его с:

$./test.sh <input.txt

Я заблокировал свой сценарий

input.txt

start
stop
sthh

Почему мой скрипт заблокирован? Как я могу это исправить?

Кстати: если я введу данные вручную, сценарий не будет заблокирован.

2 ответа2

3

Вы используете неправильный файловый дескриптор. 1 - это стандартный вывод, 0 - это стандартный вывод.

Изменить:

while read CMD <&1; do

чтобы:

while read CMD <&0; do

И это будет из файла правильно. Однако вам не нужно делать все это, так как по умолчанию read использует stdin:

while read CMD; do

Кроме того, опция -u может использоваться для чтения из определенного файлового дескриптора (по крайней мере, в bash). Так что вы могли бы сделать это также:

while read -u 0 CMD; do
2

Дескриптор файла 1 является stdout или стандартный вывод. Это означает, что вы перенаправляете ввод read из стандартного вывода. Это явно не будет работать очень хорошо; почти наверняка никогда не будет никакого ввода, ожидающего на стандартном выходе для read .

Стандартный ввод - это дескриптор файла 0 , поэтому, если вы измените <&1 на <&0 в строке 2 вашего скрипта, это сработает. Или просто отбросьте эту часть целиком; read читает из стандартного ввода по умолчанию (это в значительной степени его цель), поэтому нет необходимости явно указывать его для чтения из стандартного ввода.

Если вы хотите прочитать какой-то конкретный ввод в интерактивном режиме и разрешить перенаправление остатка из файла (или через канал), вы можете выполнить read </dev/tty .

И вам не нужен разделитель операторов точки с запятой после эха END; новая строка прекрасно работает.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .