
私は、ファイル名の入力を促し、入力が英字で始まっているか確認する関数を書いています。英字で始まっていない場合は、条件が満たされるまで、ユーザーに名前の入力を再度促します。また、ユーザーがパスを入力すると、追加のメッセージが表示されます (この割り当ての目的上、パスとは「/」を含むものすべてです)。ここで問題が発生しています...
ここに私のコードがあります...
#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
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:
1行目と3行目が異なることに注意してください
答え3
正規表現をif
ステートメント内で直接使用できます。
if [[ $name =~ ^[a-zA-Z] ]]
または:
if [[ $name =~ ^[:alpha:] ]]