我希望用户提示一个问题,然后提供答案,该答案将存储在名为 i 的变量下,然后如果答案(它是一个文件)存在并且可写,它会读取它并 grep 文件中的内容并将这些内容写入新的内容。如果该文件不存在或者用户对该文件没有足够的权限,则会提示警告,程序会休眠 3 秒,然后再次开始循环。为什么它不起作用?警告不会消失,循环也不会继续下去。
echo "$(tput setaf 4) Tell me where the file is:"
printf "\n"
a=false
while [ $a=true ]; do
read i
if [ -w $i ]
then cat $i | grep stuff > i2
else
a=true
printf "Oh something is wrong, try again!"
sleep 3
fi
done
答案1
你有语法和逻辑错误。
这$a=true
只是一个字符串,而不是比较操作。用空格分隔,以便进行比较:"$a" = true
。
完成此操作后,正如您预先设置的那样,根本不会进入循环a=false
。
如果您最终进入循环,您将无法退出,因为a
从未设置为除 之外的任何内容true
,也没有提供其他退出机制(例如break
)。
答案2
正如其他人指出的那样,代码中存在逻辑错误和语法错误。这ShellCheck 网站有利于清除语法错误。
这是我对此的看法。我有两个版本的代码。第一个(我更喜欢)没有用户交互,但在命令行上采用路径名。第二个以交互方式询问路径名。
第一个不会以交互方式提示输入路径名的原因是,如果脚本的用户在命令行上或在脚本的提示符下写入路径名,则没有什么区别,并且让脚本提示输入路径名会使其不合格从例如 cron 作业或可能没有连接终端的任何其他地方使用。
#!/bin/sh
pathname=$1
if ! grep 'pattern' <$pathname >i2; then
echo 'Something is wrong' >&2
fi
上面的语句echo
会在以下时候执行
$pathname
无法读取中的文件,或者- 该文件
i2
无法写入,或者 - 未找到该模式
$pathname
(这与您的代码不同,但请参见下文)。
错误消息被写入标准错误,就像一般诊断消息的自定义一样。
通过交互式提示和延迟:
#!/bin/bash
while true; do
read -r -p 'Pathname: ' pathname
if grep 'pattern' <$pathname >i2; then
break
fi
echo 'Something is wrong' >&2
sleep 3
done
grep
在这里,我们有一个无限循环,它从用户那里读取数据,如果调用正常则跳出循环。如果grep
由于某种原因(上述三个原因之一)失败,则会再次提示输入路径名。
这两段代码都对可读文件进行了单独的测试(允许grep
因找不到任何内容或无法写入其输出文件而失败。
首先是非交互式版本:
#!/bin/sh
pathname=$1
if [ ! -r "$pathname" ]; then
echo 'Something is wrong' >&2
fi
grep 'pattern' <$pathname >i2
然后是交互式版本:
#!/bin/bash
while true; do
read -r -p 'Pathname: ' pathname
if [ -r "$pathname" ]; then
grep 'pattern' <$pathname >i2
break
fi
echo 'Something is wrong' >&2
sleep 3
done
或者,交互式版本,其中循环仅处理用户输入和验证:
#!/bin/bash
while true; do
read -r -p 'Pathname: ' pathname
[ -r "$pathname" ] && break
echo 'Something is wrong' >&2
sleep 3
done
grep 'pattern' <$pathname >i2
答案3
尝试使用简单的 break 来停止无限循环,如下所示:
echo "$(tput setaf 4) Tell me where the file is:"
echo # This prints empty line like printf "\n"
while true; do # 'while true' or 'while :' is infinite loop
read i
if [ -r $i ] # You probably mean -r (readable) and not -w (writable)
then
cat $i | grep stuff > i2
break # 'break' ends loop
else
echo -n "Oh something is wrong, try again!" # 'echo -n' means print without newline character
sleep 3
fi
done
修改的地方都有注释和说明。