if 文内での grep

if 文内での grep

私は、ファイル名の入力を促し、入力が英字で始まっているか確認する関数を書いています。英字で始まっていない場合は、条件が満たされるまで、ユーザーに名前の入力を再度促します。また、ユーザーがパスを入力すると、追加のメッセージが表示されます (この割り当ての目的上、パスとは「/」を含むものすべてです)。ここで問題が発生しています...

ここに私のコードがあります...

#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"
}

until ループ内の if ステートメントは、いかなる状況でもパスが有効な入力ではないことをユーザーに通知せず、エラーも生成しません。if ステートメントで grep を適切に実装するにはどうすればよいですか?

答え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]$

しかし、小さな問題が 2 つ見つかりました。まず、パスを出力してから再度入力を求められます。これは、ステートメントgrep -qでスイッチ (quiet の場合は q)を使用することで解決できますif( にも機能しuntil、出力リダイレクトは不要になります)。2 つ目は、ループ内では常に 1 文字が無効であることです。これは、 の正規表現で をuntil変更することで解決できます。\w+\w*

答え2

grepuntil ステートメントは非常にかさばりますが、簡略化することができます。

この方法をお勧めします:

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:

1行目と3行目が異なることに注意してください

答え3

正規表現をifステートメント内で直接使用できます。

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

または:

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

関連情報