Сценарий для ожидания, пока пользователь не введет действительный идентификатор

В современных оболочках, таких как bash и zsh, у вас есть очень полезный перенаправитель `<<< ', который принимает строку в качестве входных данных. Так что вы бы сделали

while IFS= read -r line ; do echo $line; done <<< "$variable"

В противном случае вы всегда можете сделать

echo "$variable" | while IFS= read -r line ; do echo $line; done
-3
31.03.2019, 19:04
2 ответа

Утилита readбудет ждать пока не будут введены данные, поэтому

read username

не вернется, пока пользователь не введет что-то, что оболочка затем сохранит как $username.

Если вы под «ожиданием» подразумеваете «цикл до тех пор, пока не будет введено действительное имя пользователя», вы можете сделать что-то вроде

while true; do
    read -p 'Enter username: ' username
    if id "$username" >/dev/null 2>&1; then
        printf 'Username "%s" is valid\n' "$username"
        break
    fi
    printf 'Username "%s" is not valid\n' "$username"
    echo 'Try again...'
done

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

После этого цикла вы знаете, что у вас есть допустимое имя пользователя в $username.

Чтобы проверить, вошел ли пользователь в систему, вы можете использовать who, как вы сделали здесь (с небольшими изменениями):

if who | grep -q "^$username\>"; then
    printf 'User "%s" is logged on\n' "$username"
else
    printf 'User "%s" is not logged on\n' "$username"
fi

Имена пользователей находятся в первом столбце вывода who. Поэтому мы привязываем имя пользователя к началу строки с помощью ^. Мы также следим за тем, чтобы граница слова в конце имени пользователя соответствовала \>(, чтобы мы не обнаружили пользователя arthur, когда на самом деле ищемart).

Вместо whoмы могли бы иметь утилиту users.

Чтобы получить полное имя пользователя, выполните

name=$( getent passwd "$username" | cut -d : -f 5 | cut -d, -f 1 )

Утилита getentиспользуется, помимо прочего, для получения базы данных паролей или записи из нее. Здесь мы используем его, чтобы получить запись базы данных паролей для конкретного интересующего нас пользователя. Затем мы извлекаем полное имя из первого значения поля GECOS, разделенного запятой -.

Обратите внимание, что мы могли бы использовать getentв качестве утилиты для проверки действительных имен пользователей с (, так как она возвращает не -нулевой статус выхода, если вы используете недопустимое имя пользователя с ним ), и таким образом получил полное имя пользователя в процессе без необходимости делать другой запрос впоследствии.

Все вместе:

#!/bin/bash

while true; do
    read -p 'Enter username: ' username
    if id "$username" >/dev/null 2>&1; then
        printf 'Username "%s" is valid\n' "$username"
        break
    fi
    printf 'Username "%s" is not valid\n' "$username"
    echo 'Try again...'
done

name=$( getent passwd "$username" | cut -d : -f 5 | cut -d, -f 1 )
printf 'Full name of "%s" is %s\n' "$username" "$name"

if who | grep -q "^$username"; then
    printf '%s is logged on\n' "$name"
else
    printf '%s is not logged on\n' "$name"
fi
1
28.01.2020, 05:19

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

Что-то вроде:

#!/bin/bash
ok=1
while [ $ok -gt 0 ]; do
    read one
    < your check of $one >
    ok=$?
done
0
28.01.2020, 05:19

Теги

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