我正在编写一个函数,提示输入文件名,然后确保输入以字母字符开头,如果不是,它将重新提示用户输入名称,直到满足条件。如果用户输入路径(出于此分配的目的,路径是带有“/”的任何内容),它还会给出附加消息。这就是我遇到的问题......
这是我的代码...
#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]$
不过,我发现了两个小问题。首先,它打印路径,然后再次要求输入。这可以通过grep -q
在语句中使用 switch(q 表示安静)来解决if
(也适用于until
,则不再需要输出重定向)。其次,单个字符在循环中始终无效until
。这可以通过更改 的\w+
正则表达式来解决\w*
。
答案2
grep
直到语句非常庞大,你可以简化它。
我可以建议这个方法:
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:] ]]