嗨,我正在尝试编写一个 bash 脚本,检查输入是否包含 @ 符号,我对 bash 还比较陌生,所以请原谅任何/所有错误!到目前为止,我有:
var1="@"
var2="INPUT"
echo "input"
read INPUT
if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi
答案1
虽然你可以选择使用内置的 shell 功能来检查用户的输入是否包含@
(这在其他答案中有很好的记录),但另一种合理的方法是使用外部grep
公用事业:
#!/usr/bin/env bash
read -erp '> '
if grep -q @ <<<"$REPLY"; then
echo pass
else
echo fail
fi
传递-q
标志可防止grep
其打印匹配的行。(它还会阻止其在找到匹配项后读取更多行,但这里没有区别,因为只有一行输入。)
if
将该结构缩短为类似于的内容很诱人grep -q @ <<<"$REPLY" && echo pass || echo fail
,但我有意避免这样做:
- 在这种情况下,这可能没问题,因为打印错误的单词的唯一情况是,如果
pass
应该打印但echo
打印失败。那么,echo 可能也会打印失败fail
。 - 虽然短路
&&
和||
本身往往是合适的(我经常用它们来缩写if
没有一个else
条款),将它们一起使用,就好像它们三元组如果操作员不是一个好习惯。虽然有些命令不能失败,echo
能。 - 如果用户重定向脚本的输出被写入不可写的文件或设备,或者被用在损坏的管道、echo 等输出文本的命令可能会返回失败,导致
&&
表达式失败,并且表达式的右侧||
无法执行。 - 您可以通过运行脚本来测试在存在不可写输出设备的情况下脚本的行为
>/dev/full
。
该脚本使用了一些 bash 功能:
-e
启用 GNU readline,以便用户可以使用箭头键左右移动光标来在输入时编辑输入。- 在 bash 中,如果没有给出变量,则
read
自动将用户的输入放入变量中。REPLY
- A这里是字符串with
<<<
是一种将用户输入传递给 的便捷方法grep
。 - Bash 和一些其他 Bourne 风格的 shell(例如 dash)接受
-p
。但是POSIX 兼容的 shell 只需要理解-r
。而在某些语言中,如 ksh,-p
则有不同的含义。
(感谢盖尔哈指出-p
有时缺席然后它并不总是意味着“迅速”。)
如果你想要一个可移植到其他可能没有安装 bash 的操作系统的脚本,你可以使用:
#!/bin/sh
printf '> '
read -r line
if printf '%s' "$line" | grep -q @; then
echo pass
else
echo fail
fi
如果你愿意,你可以跳过将用户输入存储在变量中的过程,而是使用以下方式读取它:head
代替read
:
#!/bin/sh
printf '> '
if head -1 | grep -q @; then
echo pass
else
echo fail
fi
作为geirha 提到,可能被认为是head -n 1
更好的语法head -1
正式过时(尽管当前的sed
实现,或者至少是 GNU sed,-1
在其最新版本中支持,但一些非常旧的sed
实现不支持-n 1
)。
作为文档head
说,你可以使用sed
它来实现最大的可移植性。
#!/bin/sh
printf '> '
if sed 1q | grep -q @; then
echo pass
else
echo fail
fi
答案2
此bash
代码读取输入,如果输入包含符号则发出“通过”信号@
:
read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail
笔记:
[ "$var" ]
$var
是一个 bash 测试。如果字符串非空,则 返回 true 。bash 的一个功能是模式替换。它看起来像。它将中的
${var//pattern/string}
每个 替换为。在我们的例子中,是,这是一个匹配每个字符的正则表达式pattern
var
string
pattern
[^@]
除了@
. 因此,除非至少包含一个,${var//[^@]/}
否则返回一个空字符串。var
@
我们将以上两点结合起来:
[ "${var//[^@]/}" ]
${var//[^@]/}
仅当非空时此测试才会成功,并且仅当至少包含一个${var//[^@]/}
时才非空。var
@
使用显式的 if-then-else:
read -p "Input: " var
if [ "${var//[^@]/}" ]
then
echo Pass
else
echo Fail
fi
POSIX Shell
以下内容在dash
( /bin/sh
) 下有效,并且应该可以在任何 POSIX shell 下有效:
printf "Input: "
read var
case "$var" in
*@*) echo Pass
;;
*) echo Fail
;;
esac
POSIX shell 不支持-p
以下选项read
printf
。因此,使用和的组合read
。此外,由于缺少 的高级变量扩展功能bash
,该case
语句可用于全局匹配。
Android Shell
使用我的android上的默认shell,可以进行以下工作:
echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
echo Pass
else
echo Fail
答案3
bash 中的首选方式是使用 的模式匹配功能[[ ... ]]
。
#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
printf '<%s> contains @\n' "$input"
fi
您sh
可以改用脚本case
。
#sh
printf 'Input: '
read -r input
case $input in
*@*) printf '<%s> contains @\n' "$input" ;;
esac
另请参阅测试和条件Bash 指南的章节。
答案4
在较新版本的 bash 中,你应该能够使用正则表达式匹配通过=~
扩展测试运算符:
$ read -p "input: " input
input: quertyuiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
no match
$
$ read -p "input: " input
input: qwerty@uiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
match
expr
在任何兼容 POSIX 的系统中都应该有效的替代方法是在 shell 中使用dash
:
$ read input
qwertyuiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
no match
$
$ read input
qwerty@uiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
match
$