Возвращаем переменную из цикла while в bash - PullRequest
0 голосов
/ 22 июня 2019

Я пытаюсь использовать цикл while для многократного запроса имени пользователя во время регистрации пользователя, пока не будет предоставлено действительное имя пользователя (то есть оно НЕ было заявлено).

К сожалению, я был толькопрограммирую на bash менее 70 часов, поэтому я не знал, как это сделать.Сначала я думал использовать goto, как в пакетных сценариях Windows, если возникла проблема с именем пользователя, но, видимо, в bash это не так, и циклы кажутся рекомендуемым маршрутом.Я не был знаком с циклами в bash, поэтому провел некоторое исследование, пока не нашел хороший ответ на вопрос о том, как это сделать.Это не точный пост (я не могу найти его сейчас), но я смотрел на вопросы , как этот .

Полученный код выглядит так:

echo -e "Now, choose a unique username. No special characters, please."
uniqueuser=0 # Assume a valid username has not been chosen from the get-go
while [ "$uniqueuser" == "0" ]
do
    read -p "Username: " username
    lusername=`echo $username | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/` #lowercase username
    if [ "$lusername" == "admin" ] || [ "$lusername" == "administrator" ] || [ "$lusername" == "npstn" ] || [ "$lusername" == "phreak" ] || [ "$lusername" == "guest" ] || [ "$lusername" == "user" ] || [ "$lusername" == "sysop" ]
    then
        echo -e "That username is reserved. Please pick another username."
    else
        username=`php /home/com/encode.php "$username"`
        available=`curl "https://example.com/redacted/redacted.php?key=$key&type=checkusername&username=$username" --silent`
        if [ "$available" == "1" ]
        then
            uniqueuser=$((1)) # Username is unique and acceptable
        else
            echo -e "That username is taken. Please choose another one."
        fi
    fi
done <input.data # so that username variable persists outside of while loop
echo -e "That username is available... or was... now, it's yours!"
echo -e "On this board, we have no annoying password length or complexity requirements. That said, your password cannot be null, nor can it use the plus symbol. Choose wisely!"

Когда эта часть сценария оболочки достигнута, я вижу:

Now, choose a unique username. No special characters, please.
/home/com/redacted.sh: line 4: input.data: No such file or directory
That username is available... or was... now, it's yours!
On this board, we have no annoying password length or complexity requirements. That said, your password cannot be null, nor can it use the plus symbol. Choose wisely!

Причина, по которой "input.data" используется для получения переменной $ username из подоболочки и возврата восновная оболочка.Однако, это, кажется, вызывает ошибку.Как я могу это исправить?

1 Ответ

3 голосов
/ 22 июня 2019

Вы неправильно прочитали источники, на которые полагаетесь. Перенаправление стандартного ввода из файла, например:

count=0
while IFS= read -r line; do
  (( ++count )) # or do something else
done < input.data
echo "$count"   # will print number of lines in the file input.data

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

# DO NOT DO THIS; this is the practice the other answers were teaching how to avoid.
count=0
cat input.data | while IFS= read -r line; do
  (( ++count )) # or otherwise modify data within the loop
done
echo "$count"   # will print 0, because the loop was in a subshell

Это изменение не является обязательным и неуместным, если вы вводите данные из стандартного ввода, а не из файла.

Проблема cat input.data |, для которой < input.data является заменой. Если в вашем исходном коде не было cat input.data |, вам не нужно использовать < input.data для его замены.


Демонстрация того, что цикл while read может читать из стандартного ввода и сохранять значения его переменных без такого перенаправления:

count=0
prompt='Enter a string, or a blank line to stop: '
while IFS= read -r -p "$prompt" line && [[ $line ]]; do
  (( ++count ))
  printf 'Line %d: %s\n' "$count" "$line"
done
echo "Final counter is $count"

... сохраняет то же значение для $count вне цикла, в котором он находится внутри цикла, когда вводится пустая строка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...