输入验证与字符串转换

0 投票
1 回答
515 浏览
提问于 2025-04-16 17:43

我有一个脚本,它会从用户那里获取输入,我想先验证这个输入,然后再把用户输入的内容转换成预定义的格式。输入应该像这样:

my_script -c 'formatDate(%d/%m) == 23/5 && userName == John Dee && status == c

目前我只在处理formatDate()这一部分。主要的规则有:

  • year, month, day的格式字符串可以以任何顺序出现
  • 如果缺少m(或y或d),就用current_month来补上;其他的也一样
  • 格式字符串和数值必须使用相同的分隔符
  • 键和值之间必须用==分开
  • 不同的条件必须用&&分开
  • 可以有一个或多个条件

所以,对于给定的例子,它应该返回20110523作为一个有效的条件。经过一番努力,我得到了这个,基本上是可以工作的:

#!/usr/bin/env python
#
import sys, re
from time import localtime, strftime

theDy = strftime('%d', localtime())
theMn = strftime('%m', localtime())
theYr = strftime('%Y', localtime())

def main(arg):

    print "input string: %s" % arg
    arg = "".join(arg.split()).lower()

    if arg.startswith('=') or re.search('===', arg) or "==" not in arg:
       sys.exit("Invalid query string!")
    else: my_arg = arg.split('&&')

    c_dict = {}

    for ix in range(len(my_arg)):
       LL = my_arg[ix].split('==')
       #LL = dict(zip(LL[:-1:2], LL[1::2]))

       # don't add duplicate key
       if not c_dict.has_key(LL[0]):
          c_dict[LL[0]] = LL[1]

       for k,v in sorted(c_dict.items()):
          if k.startswith('formatdate') :
             ymd = re.sub(r'[(,)]', ' ', k).replace('formatdate','')
             ymd = (str(ymd).strip()).split('/')
             if len(ymd) <= 3 and len(ymd) == len(v.split('/')):
                d_dict = dict(zip(ymd, v.split('/')))

                if not d_dict.has_key('%y'):
                   d_dict['%y'] = theYr
                if not d_dict.has_key('%m'):
                   d_dict['%m'] = theMn
                if not d_dict.has_key('%d'):
                   d_dict['%d'] = theDy

             else: sys.exit('date format mismatched!!')

             Y = d_dict['%y'];

             if d_dict['%m'].isdigit() and int(d_dict['%m']) <=12:
                M = d_dict['%m'].zfill(2)
             else: sys.exit("\"Month\" is not numeric or out of range.\nExiting...\n")

             if d_dict['%d'].isdigit() and int(d_dict['%d']) <=31:
                D = d_dict['%d'].zfill(2)
             else: sys.exit("\"Day\" is not numeric or out of range.\nExiting...\n")

             # next line needed for future use  
             fmtFile = re.compile('%s%s%s' % (Y,M,D))
             print "file_name is: %s" % Y+M+D

if __name__ == "__main__":
    main('formatDate(%d/%m)== 23/5')

我想问的问题是:

  • 我这样做是不是太复杂或者太耗资源了?有没有更简单的方法?
  • 如何识别用户使用了哪个“分隔符”(而不是使用一个固定的分隔符)?

谢谢你的时间。祝好!!

1 个回答

1

你并不是在制造麻烦,但你有没有想过扩展用户请求的语法会带来什么后果?

最简单的解析器是堆栈算法。你可以把它用在用户请求上,这样就能轻松扩展语法。你可以在这里找到Python的实现这里

撰写回答