2013-03-28 20 views
2

Я делаю цикл, который принимает входные данные из файла, чтобы определить, разрешено ли пользователю использовать определенную программу.bash for loop with file input not working

#!/bin/bash 

boole=false 

echo "Username: " 
read username 

echo "debug0" 

for((line=1; $boole=false; line++)); do 
    echo "debug.5" 
    auth=`head -n $line users | tail -n $line` 

    echo "debug1" 

    if [ $username = $auth ]; then 
     echo "debug2" 
     echo "authentication success" 
     read 
     exit 0 
    fi 

    if [ $auth = "#end" ]; then 
     echo "debug3" 
     echo "authentication failed" 
     read 
     exit 0 
    fi 
done 

echo "skip everything" 

Выход

Username: 
admin 
debug0 
skip everything 

Файл с пользователями имеет

root 
admin 
... 
#end 

#end и boole должен сказать петлю до конца

Это просто этап отладки так он фактически не выполняет какую-либо программу, это просто должно сказать мне, что r, или нет, пользователю разрешено использовать его.

+2

В вашем цикле for '$ boole = false' будет расширяться до' false = false', вероятно, не то, что вы хотите. удалите '$'. Удачи. – shellter

+0

Это кажется неэффективным способом чтения файла - почему бы просто не использовать цикл while while? – FatalError

+3

Или, еще лучше, 'grep -q"^$ {username} $ "users && .....'? – twalberg

ответ

0

Петли в bash не похожи на петли C. Базовый синтаксис:

for arg in [list] 
do 
    [command(s)...] 
done 

Существует, однако синтаксис C-стиль, как тот, который вы используете:

for ((x=1; x<=3; x++)) 
{ 
    echo $x 
} 

Как уже упоминалось в комментариях, когда вы пишете $boole=false внутри двойных круглых скобок, $boole разыменовывается до обрабатывается содержимое двойных скобок и, таким образом, становится false=false. Кроме того, когда вы заключите что-то в двойные круглые скобки, вы должны использовать == для сравнения. В любом случае, будь то $boole=false или $boole==false, они оба будут истинными, поскольку первый успешно присваивает false до false, а второй - истиной из-за того, что значение false==false является истинным.

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

bool=true 
int=1 
while $bool; do 
    echo $int 
    ((int++)) 
    if [[ $int == 10 ]]; then 
     bool=false 
    fi 
done 
echo $int 
+0

У 'bash' есть C-стиль для петель. – chepner

+0

Да, я думаю, что мой ответ немного по этому поводу. – beruic

+0

Если у вас есть bash 4, я бы попросил Чарльза попробовать. В качестве альтернативы я бы использовал Python :) – beruic

0

Использовать цикл while, а не цикл for, при чтении файлов. Это отражено в http://mywiki.wooledge.org/BashFAQ/001

while read -r line; do 
    something_with "$line" 
done 

В этом случае, вы можете использовать ассоциативный массив для хранения списка авторизованных пользователей:

declare -A authorized_users=() 
while read -r username; do 
    authorized_users[$username]=1 
done <input_file 

... и после этого вы можете проверить, если пользователь находится в этот список, как так:

if [[ ${authorized_users[$possible_username]} ]]; then 
    echo "User is authorized!" 
fi 

Обратите внимание, что ассоциативный синтаксис массив был добавлен в Баш 4.

0

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

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

поэтому я обновил скрипт для петли вокруг и попросить ввода пользователя, если он соответствует список неудачу:

(извините, если это теперь далеко, что вы хотели - я думаю, что это, возможно, было больше, что вы хотели ?)

#!/bin/bash 


echo "debug0" 
i=0; 

#Maybe you want something to measure bad input 
# right now only if user puts in #end 3 times will this pass 
# so again look at the logics if needed add the attempts++ to skip everything.. 
max_attempts=3; 

# current running attempts set as 0; 
attempts=0; 



#start function repeats for user input 
function start() { 
    echo "Username: " 
    read input 
    # run process input function 
    process_input 
} 

# The process input function works out what user has put in 
function process_input() { 
    # Go through for loop of users command 
    loggedin=$(users); 
    for auth in ${loggedin[@]}; do 
     echo "debug.5" 
     echo "debug1" 
     # if current value from users output matches the user input 
     if [[ $auth == $input ]]; then 
     echo "debug2" 
     echo "authentication success" 
     #unsure what you are reading here since your not asking for a prompt 
     read; 
     exit 0; 
     # either if input matches #end or anything after 3 attempts that 
     # does not match admin 
     elif [[ $auth == "#end" ]] || [[ $attempts -gt $max_attempts ]]; then 

     echo "debug3" 
     echo "authentication failed - failed attempts $attempts " 
     ((attempts++)) 

     start; 
     fi 
done 

echo "skip everything" 
# removed comment from start function below if you want to get user to re-enter 
start; 

} 

# begin your program by running the start function 
start;