如何检查一个variables是否存在于BASH的列表中
我正在尝试在bash中编写一个脚本来检查用户input的有效性。
我想匹配input(比如variablesx
)到一个有效值列表。
我现在提出的是:
for item in $list do if [ "$x" == "$item" ]; then echo "In the list" exit fi done
我的问题是如果有一个更简单的方法来做到这一点,
就像大多数编程语言的list.contains(x)
一样。
加成:
说清单是:
list="11 22 33"
我的代码将回显消息只为这些值,因为list
被视为一个数组而不是一个string,所有的string操作将validation1
而我希望它失败。
[[ $list =~ (^|[[:space:]])$x($|[[:space:]]) ]] && echo 'yes' || echo 'no'
或者创build一个函数:
contains() { [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && exit(0) || exit(1) }
使用它:
contains aList anItem echo $? # 0: match, 1: failed
马特是正确的,但你应该引用$ x并考虑任何types的“空格”(如新行)
[[ $list =~ (^|[[:space:]])"$x"($|[[:space:]]) ]] && echo 'yes' || echo 'no'
所以,即
# list_include_item "10 11 12" "2" function list_include_item { local list="$1" local item="$2" if [[ $list =~ (^|[[:space:]])"$item"($|[[:space:]]) ]] ; then # yes, list include item result=0 else result=1 fi return $result }
结束然后
`list_include_item "10 11 12" "12"` && echo "yes" || echo "no"
要么
if `list_include_item "10 11 12" "1"` ; then echo "yes" else echo "no" fi
请注意,您必须在variables的情况下使用""
:
`list_include_item "$my_list" "$my_item"` && echo "yes" || echo "no"
如果使用双括号,则也可以在case语句外使用(*通配符):
string='My string'; if [[ $string == *My* ]] then echo "It's there!"; fi
怎么样
echo $list|grep $x
你可以检查输出或$?
作出决定。
考虑利用关联数组的键。 我会认为这胜过正则expression式/模式匹配和循环,虽然我没有分析它。
declare -A list=( [one]=1 [two]=two [three]='any non-empty value' ) for value in one two three four do echo -n "$value is " # a missing key expands to the null string, # and we've set each interesting key to a non-empty value [[ -z "${list[$value]}" ]] && echo -n '*not* ' echo "a member of ( ${!list[*]} )" done
输出:
one is a member of ( one two three ) two is a member of ( one two three ) three is a member of ( one two three ) four is *not* a member of ( one two three )
我发现使用echo $LIST | xargs -n1 echo | grep $VALUE
更容易 echo $LIST | xargs -n1 echo | grep $VALUE
echo $LIST | xargs -n1 echo | grep $VALUE
如下图所示:
LIST="ITEM1 ITEM2" VALUE="ITEM1" if [ -n "`echo $LIST | xargs -n1 echo | grep -e \"^$VALUE`$\" ]; then ... fi
这适用于以空格分隔的列表,但可以通过执行以下操作将其适用于任何其他分隔符(如:):
LIST="ITEM1:ITEM2" VALUE="ITEM1" if [ -n "`echo $LIST | sed 's|:|\\n|g' | grep -e \"^$VALUE`$\"`" ]; then ... fi
请注意, "
是testing工作所必需的。
如果列表在脚本中是固定的,我喜欢以下最好的:
validate() { grep -F -q -x "$1" <<EOF item 1 item 2 item 3 EOF }
然后使用validate "$x"
来testing是否允许$x
。
如果你想要一个单行,而不关心项目名称中的空格,你可以使用这个(注意-w
而不是-x
):
validate() { echo "11 22 33" | grep -F -q -w "$1"; }
笔记:
- 这是POSIX
sh
兼容。 -
validate
不接受子string(如果需要的话,删除-x
选项以grep)。 -
validate
将它的参数解释为一个固定的string,而不是一个正则expression式(如果你想要的话,删除-F
选项来grep)。
示例代码来锻炼function:
for x in "item 1" "item2" "item 3" "3" "*"; do echo -n "'$x' is " validate "$x" && echo "valid" || echo "invalid" done
如果您的值列表要在脚本中进行硬编码,则使用case
进行testing非常简单。 这里有一个简短的例子,你可以适应你的要求:
for item in $list do case "$x" in item1|item2) echo "In the list" ;; not_an_item) echo "Error" >&2 exit 1 ;; esac done
如果列表在运行时是一个数组variables,其他答案之一可能更适合。
恕我直言,最简单的解决scheme是prepend和追加原始string与空格,并与[[ ]]
检查正则expression式
haystack='foo bar' needle='bar' if [[ " $haystack " =~ .*\ $needle\ .* ]]; then ... fi
这个值不会是假的,值包含针头作为子string,例如干草堆foo barbaz
。
(这个概念被无耻地从JQuery的hasClass()
方法中窃取)
例子
$ in_list super test me out NO $ in_list "super dude" test me out NO $ in_list "super dude" test me "super dude" YES # How to use in another script if [ $(in_list $1 OPTION1 OPTION2) == "NO" ] then echo "UNKNOWN type for param 1: Should be OPTION1 or OPTION2" exit; fi
in_list
function show_help() { IT=$(CAT <<EOF usage: SEARCH_FOR {ITEM1} {ITEM2} {ITEM3} ... eg abcd -> NO abad -> YES "test me" how "test me" -> YES ) echo "$IT" exit } if [ "$1" == "help" ] then show_help fi if [ "$#" -eq 0 ]; then show_help fi SEARCH_FOR=$1 shift; for ITEM in "$@" do if [ "$SEARCH_FOR" == "$ITEM" ] then echo "YES" exit; fi done echo "NO"