grep в операторе if

grep в операторе if

Я пишу функцию, которая запрашивает имя файла, а затем проверяет, начинается ли ввод с символа альфа, если нет, она повторно запрашивает имя у пользователя, пока не будут выполнены критерии. Она также выдает дополнительное сообщение, если пользователь вводит путь (путь — это все, что содержит '/' для целей этого задания). Вот тут-то у меня и возникает проблема...

вот мой код...

#1) make a getname function that will prompt for filename
function getname(){
trap control_c SIGINT
local fname=$1;

#if there is no input prompt user for file name
if [ ! $1 ]; then
        read -p "Enter a file name: " fname;
fi;

#until grep is given a valid file name
until ( grep -E '^[a-zA-Z_]\w+$' <<< "$fname" > /dev/null 2>&1); do





        #this is were the error is
        if echo "$fname" | grep -E '/';





         then                           #this tests if fname is a file directory
        echo "Paths are not a legal file name.";
        fi;
        read -p "Enter a legal file name: " fname;
done
echo "$fname"
}

Оператор if в цикле until ни при каких обстоятельствах не будет сообщать пользователю, что пути не являются допустимым вводом, а также не выдаст никаких ошибок. Как бы мне правильно реализовать grep в операторе if?

решение1

На самом деле у меня это работает в Fedora 26 с использованием GNU bash, version 4.4.12(1)-release (x86_64-redhat-linux-gnu). Функция продолжает спрашивать, указан ли путь. Смотрите вывод.

[@host testing]$ getname
Enter a file name: ab/sav
ab/sav
Paths are not a legal file name.
Enter a legal file name: abc                    
abc
[@host testing]$

Однако я обнаружил две небольшие проблемы. Во-первых, он печатает путь, а затем снова запрашивает ввод. Это можно решить, используя switch grep -q(q для quiet) в ifоператоре (также работает для until, тогда перенаправление вывода больше не нужно). Во-вторых, один символ всегда недопустим в untilцикле. Это можно решить, изменив \w+в regex для \w*.

решение2

grepв операторе until очень громоздкий, вы можете упростить его.

Могу предложить такой метод:

until [ ! -z "$fname" ]; do
        read -p "Enter a legal file name: " fname
        grep -E '^[a-zA-Z_]\w+$' <<< "$fname" > /dev/null 2>&1

        #check exit code
        if [ $? -ne 0 ]; then
                echo "Paths are not a legal file name."
                fname=""
        fi
done

При необходимости добавьте любые другие условия внутрь цикла until.

Если вы хотите обрабатывать сообщения для пользователей, то вы можете использовать этот прием без нескольких readпоявлений команд:

fname=""
message_for_user="Enter a file name: "

until [ ! -z "$fname" ]; do
        read -p "$message_for_user" fname
        grep -E '^[a-zA-Z_]\w+$' <<< "$fname" > /dev/null 2>&1

        #check exit code
        if [ $? -ne 0 ]; then
                echo "Paths are not a legal file name."
                fname=""
                message_for_user="Enter a legal file name: "
        fi
done

Вывод будет следующим:

Enter a file name: 1laha
Paths are not a legal file name.
Enter a legal file name:

Обратите внимание, что первая и третья строки отличаются.

решение3

Вы можете использовать регулярное выражение ifнепосредственно в выражении:

if [[ $name  =~ ^[a-zA-Z] ]]

или:

if [[ $name  =~ ^[:alpha:] ]]

Связанный контент