如何在Bash中清理用户输入

时间:2016-03-01 23:10:40

标签: linux bash shell redhat

我正在用bash编写一个脚本,它会提示用户输入两个输入。这些输入分配给变量' TO_SCHEMA'和' FROM_SCHEMA'分别

我需要一种方法来验证正确的输入。我的要求如下:

每个变量都有3个可接受的值。它们对于两个变量都是相同的值,但两个变量必须在这三个列表中,并且它们不能是相同的值。

因此,如果值为' myco',' myco_int'和' teambatch',则两个变量必须是其中一个值,但它们可以&# 39;是一样的。

${TO_SCHEMA} = myco && ${FROM_SCHEMA} = myco_int
   Pass

${TO_SCHEMA} = myco_int && ${FROM_SCHEMA} = myco_int
   Fail

${TO_SCHEMA} = mco && ${FROM_SCHEMA} = myco_int
   Fail

${TO_SCHEMA} = myco && ${FROM_SCHEMA} = donkey
   Fail

我怎样才能做到这一点?

我从一个充满AND和OR运算符的if语句开始,但是它们变得很难看。我对正则表达式的体验是有限的,我对sed和awk的经验是不存在的,但我愿意学习并尝试任何这些。 任何帮助将不胜感激。

编辑:

我还应该提一下,这个脚本只是为了一个小小的乏味的一次性工作,我必须做很多工作,我很乐意自动化。如果我不是使用它的人,那么我的团队中的某个人就是。所以这个输入检查是一个需要而不是需要。如果脚本由于输入错误而中断,那么它不是世界末日。我希望它能更优雅地处理糟糕的输入。

再次编辑: 我感谢大家的建议,但我必须做出一些澄清。这些值实际上不是模式1,2和3.出于安全原因,我不允许提供正确的名称,但我将它们更改为更类似于真实值的值。

2 个答案:

答案 0 :(得分:1)

最简单的解决方案需要bash 4.3。您只需将有效输入存储为关联数组的键,然后使用-v运算符检查给定输入是否定义为键。

declare -A valid
# Values don't matter, as long as the key exists.
# I put spaces in the keys just to show it's possible
valid[schema 1]=
valid[schema 2]=
valid[schema 3]=

if [[ $FROM_SCHEMA != $TO_SCHEMA && -v valid[$FROM_SCHEMA] && -v valid[$TO_SCHEMA] ]]; then
    # inputs pass
else
    # inputs fail
fi

在早期的4.x版本中,您可以稍微区别地检查关联数组中的未定义值。

declare -A valid
# Now, we need to make sure the values are non-null, but
# otherwise it doesn't matter what they are
valid[schema 1]=1
valid[schema 2]=1
valid[schema 3]=1
if [[ $FROM_SCHEMA != $TO_SCHEMA && -n ${valid[$FROM_SCHEMA]} && -n ${valid[$TO_SCHEMA]} ]]; then
    # inputs pass
else
    # inputs fail
fi

bash 4之前,没有关联数组,您可以回退到扫描存储在常规数组中的有效输入列表。

valid=("schema 1" "schema 2" "schema 3")
if [[ $TO_SCHEMA == $FROM_SCHEMA ]]; then
    # inputs fail
else
    ok_count=0
    # We've already established that TO and FROM are different,
    # so only at most one per candidate can match.
    for candidate in "${valid[@]}"; do
        if [[ $TO_SCHEMA == $candidate || $FROM_SCHEMA == $candidate ]]; then
            ok_count+=1
        fi
    done
    if (( ok_count == 2 )); then
        # inputs pass
    else
        # inputs fail
    fi
fi

答案 1 :(得分:0)

注意,快速而肮脏,缺乏优雅,但有效。这假设您的schema1答案是准确的。我正确地读了你的问题。如果您从中获取数据,您将替换[您的输入1]等,它是对用户输入的读取权吗?为什么不让他们从列表中选择它?

values='1 2 3'
result1=''
result2=''

input1=[your input 1]
input2=[your input 2]
# force to lower case
input1=$(tr '[A-Z]' '[a-z]' <<< "$input1" )
input2=$(tr '[A-Z]' '[a-z]' <<< "$input2" )

for item in $values
do
    if [[ -n $( grep -E "^schema$item$" <<< $input1 ) ]];then
        values=$(sed "s/$item//" <<< $values )
        result1=$input1
    fi
done
for item in $values
do
    if [[ -n $( grep -E "^schema$item$" <<< $input2 ) ]];then
        result2=$input2
    fi
done

if [[ -z $result1 ]];then
    echo 'Your first entry is not right: ' $input1
elif [[ -z $result2 ]];then
    echo 'Your second entry is not right: ' $input2
else
    echo 'Valid data'
fi

请注意,如果您只是想测试文字的完整字符串,那就可以了:

values='schema1 schema2 schema3'

然后删除&#39;架构&#39;从grep测试,然后只是寻找完整的字符串的东西。并且sed只会从值列表中删除找到的项目。

如果您依赖于用户输入的输入,则必须强制降低它以避免痉挛用户操作或对grep执行不区分大小写的模式匹配,但最好在测试之前强制降低它。< / p>

input1=$(tr '[A-Z]' '[a-z]' <<< "$input1" )