我决定为验证 while 循环创建 fn ,我将在整个代码中重复使用它:
loopFN() {
while true; do
if [ "$1" == "null" ] || ([ "$2" == "phone number" ] && ! [[ "$1" =~ $phone_regex ]]); then
printf 'enter a valid %s\n' "$2"
read
$1=$REPLY
else
break
fi
done
}
我这样称呼它:
local number="null"
loopFN "$number" "phone number"
我的电话号码正则表达式是:
phone_regex="^[0-9]{3}-[0-9]{3}-[0-9]{4}"
我得到的错误是:
./newmenu.sh: line 27: null=dasd: command not found
其中“dasd”是我在提示时输入的内容
重用 while 循环是不好的做法吗?我应该重写它多少次吗?或者我的语法有问题吗?
我猜问题就在这里(错误引用的第 27 行):
$1=$REPLY
我试图设置传入 fn 的变量,在本例中为 $number,我最初的想法是它不起作用,因为 var 是本地的,但我删除了 local 关键字,错误仍然存在
编辑:
我根据建议添加了一些更改:
loopFN() {
while true; do
if [[ $1 = null ]]; then
printf>&2 'enter a valid %s\n' "$2"
IFS= read -r "$1"
elif [[ $1 = null || ( $2 = 'phone number' && ! $1 =~ $phone_regex ) ]]; then
printf>&2 "enter a valid phone number\n"
IFS= read -r "$1"
else
break
fi
done
}
$1=$REPLY
=
不被理解为变量赋值,因为( )的左边$1
不是有效的变量名,因此它仅被视为命令参数或命令参数列表(因为并且$1
未$REPLY
加引号,所以受 split+glob 的影响)它被视为命令名称。你需要:
要要求 shell
contents_of_$1=$REPLY
作为 shell 代码进行计算,并假设 的内容$1
是有效的变量名称,则会将 的值分配$REPLY
给相应的变量(如果$1
是reboot;foo
,则显然会重新启动)。在这里你还可以这样做:
它将使用作为参数
read
的内容进行调用,并且不关心也无法知道该变量名是按字面传递还是扩展的结果。$1
read
这仍然是一个命令注入漏洞(就像when
$1
is 一样foo[`reboot`]
)。无论如何,读取一行的语法是
IFS= read -r line
, 不是。read line
另请注意
(...)
,在 Korn 风格[[...]]
构造之外启动一个子 shell,您的更应该是:
如果
$1
是一个变量名,那就$1 =~ $phone_regex
没什么意义了。电话号码很少是有效的变量名称。如果您打算检查名称为 的变量的内容
$1
,那么您可以使用${!1}
bash 语法来取消引用变量,或者按照 ChatGPT 的建议,将 ksh93 样式的名称引用与较新版本的 bash 一起使用。请注意,无论如何,您需要传递给函数的是变量名称 (
number
) 而不是值 ( )。$number
用户提示和交互通常会转到 stderr,stdout 被保留用于命令产生的实际输出,其他东西可能想要重用/后处理。
特别是对于
bash
shell,您可以使用-p
其read
内置选项来发出p
rompt(它也会发送到 stderr):而在大多数其他类似 Korn 的 shell 中,语法是:
如果该函数旨在输入电话号码,反复询问直到用户输入有效的电话号码,并将其返回到第一个参数中提供名称的变量中,然后使用 bash 特定的语法,它看起来像:
(使用
[0123456789]
而不是[0-9]
as[0-9]
可以匹配任何内容,并在末尾和开头锚定正则表达式)。对于
input
采用输入类型和验证正则表达式作为参数的通用函数:请注意
_
局部变量中的前缀,以便用户可以执行input type type '^(good|bad)$'
例如操作,而不会导致局部变量与他们想要返回的$type
用户变量发生冲突。$type