
我正在編寫一個函數,提示輸入檔案名,然後確保輸入以字母字元開頭,如果不是,它將重新提示使用者輸入名稱,直到滿足條件。如果使用者輸入路徑(出於此分配的目的,路徑是帶有“/”的任何內容),它也會給出附加訊息。這就是我遇到的問題......
這是我的代碼...
#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:] ]]