bash 脚本检查输入是否有@

bash 脚本检查输入是否有@

嗨,我正在尝试编写一个 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 功能:

如果你想要一个可移植到其他可能没有安装 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}每个 替换为。在我们的例子中,是,这是一个匹配每个字符的正则表达式patternvarstringpattern[^@]除了 @. 因此,除非至少包含一个,${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以下选项readprintf。因此,使用和的组合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
$ 

相关内容