我试图在bash中编写一个脚本,检查用户输入的有效性。 我想将输入(变量x)匹配到一个有效值列表。

我现在想到的是:

for item in $list
do
    if [ "$x" == "$item" ]; then
        echo "In the list"
        exit
    fi
done

我的问题是,如果有更简单的方法, 对于大多数编程语言,类似list.contains(x)。

列表是:

list="11 22 33"

我的代码将只对这些值回显消息,因为list被视为数组而不是字符串, 所有的字符串操作都将验证1,而我希望它失败。


当前回答

在我看来,最简单的解决方案是在原始字符串前加上一个空格,并使用[[]]检查正则表达式。

haystack='foo bar'
needle='bar'

if [[ " $haystack " =~ .*\ $needle\ .* ]]; then
    ...
fi

对于包含needle作为子字符串的值,这将不会是假阳性,例如用haystack foo barbaz。

(这个概念是从JQuery的hasClass()-Method中偷来的)

其他回答

假设TARGET变量只能是“二项式”或“回归”,那么如下所示:

# Check for modeling types known to this script
if [ $( echo "${TARGET}" | egrep -c "^(binomial|regression)$" ) -eq 0 ]; then
    echo "This scoring program can only handle 'binomial' and 'regression' methods now." >&2
    usage
fi

您可以通过使用|(管道)字符分隔更多字符串到列表中。

使用egrep的优点是可以轻松地添加大小写不敏感(-i),或者使用正则表达式检查更复杂的场景。

如果您的值列表将硬编码在脚本中,那么测试用例相当简单。下面是一个简短的例子,你可以根据自己的需求进行调整:

for item in $list
do
    case "$x" in
      item1|item2)
        echo "In the list"
        ;;
      not_an_item)
        echo "Error" >&2
        exit 1
        ;;
    esac
done

如果列表在运行时是一个数组变量,那么其他答案中的一个可能更适合。

如果将列表固定在脚本中,我最喜欢以下几个:

validate() {
    grep -F -q -x "$1" <<EOF
item 1
item 2
item 3
EOF
}

然后使用验证“$x”来测试是否允许使用$x。

如果你想要一行代码,并且不关心项目名称中的空格,你可以使用这个(注意-w而不是-x):

validate() { echo "11 22 33" | grep -F -q -w "$1"; }

注:

这是POSIX sh兼容的。 Validate不接受子字符串(如果需要,可以删除grep的-x选项)。 Validate将其参数解释为固定字符串,而不是常规字符串 表达式(如果需要,可以删除grep的-F选项)。

演示函数的示例代码:

for x in "item 1" "item2" "item 3" "3" "*"; do
    echo -n "'$x' is "
    validate "$x" && echo "valid" || echo "invalid"
done

如果你使用双括号,你也可以在case语句外使用(*通配符):

string='My string';

if [[ $string == *My* ]]
then
echo "It's there!";
fi

之前的答案没有使用tr,我发现它对grep很有用。假设列表中的项以空格分隔,检查精确匹配:

echo $mylist | tr ' ' '\n' | grep -F -x -q "$myitem"

如果条目在列表中,这将返回退出代码0,如果不在列表中,则返回退出代码1。

最好将它作为函数使用:

_contains () {  # Check if space-separated list $1 contains line $2
  echo "$1" | tr ' ' '\n' | grep -F -x -q "$2"
}

mylist="aa bb cc"

# Positive check
if _contains "${mylist}" "${myitem}"; then
  echo "in list"
fi

# Negative check
if ! _contains "${mylist}" "${myitem}"; then
  echo "not in list"
fi