通过一道奇葩面试题来体验下awk的强大


面试题内容
需求:以"|"为分隔符,打印第一字段第一个字符是1,第二个字段第二个字符是2,第三个字段第三个字符是3,以此类推;倒数第二个字段前8个字符是当天日期如“20140610”。

源文件raw_data.txt:

$ date +%Y%m%d

我用Python实现的代码:
$ ./check_string.py

#!/usr/bin/env python

import datetime

def check_item(string):
    item_list = string.split('|')
    for item_id in range(0,len(item_list)):
        try:
            item_sub_list = list(item_list[item_id])
        except IndexError:
            return False

        special_item_id = len(item_list) - 2
        expect_item_sub_value = item_id + 1
        if item_id != special_item_id:
            try:
                if not item_sub_list[item_id] != expect_item_sub_value:
                    return False
            except IndexError:
                return False
        else:
            if not datetime.datetime.now().strftime("%Y%m%d") == ''.join(item_sub_list[0:8]):
                return False

    return True

if __name__=='__main__':
    filename = 'raw_data.txt'

    with open(filename) as fp:
        for line in fp:
            if check_item(line.replace('\n','')):
                print "Matched: {0}".format(line.replace('\n',''))

网友“运维@苏东”用awk实现的代码:
$ cat raw_data.txt | awk -F\| 'BEGIN{d=strftime("%Y%m%d")} { i=1;j=NF-1;k=0;while(i<j-1){if ( substr($i,i,1) == i ){k++;}; i++}; if (k==i-1 && substr($j,1,8) == d && substr($NF,NF,1) == NF) {print $0} }'

,

  1. #1 by mcsrainbow on 2016/09/20 - 23:19

    尽显单行脚本的强悍!

  2. #2 by Ronaldo on 2016/09/21 - 15:19

    来个蛋疼版本的
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import datetime

    data = '''1|12|a7f865ce-b274-4b23-890c-893c7d1f2198||||2016082055104
    3|22|bd166d4f-5222-4d69-a277-deb543db1a9d||||20141117012936|
    1|a2af|1135ea2-067a-4d4c-b56f|01442332|308g5dfg|955226r9|2016092137|20150428102737
    1|a2af|1135ea2-067a-4d4c-b56f|01442332|308g5dfg|955226r9|2016092237|20150428102737
    1|222|1f3f1950-6b0e-4459-a1ee|sad4sadf|adsa5dfd|7746765|2016092002|'''

    def check(idx, string):
    try:
    return int(string[idx - 1]) == idx
    except (IndexError, ValueError):
    return False

    xxoo = lambda o: all(o[:-2] + [o[-1]])

    d = datetime.datetime.now().strftime('%Y%m%d')

    print [line if xxoo(map(lambda y: check(*y), [x for x in enumerate(line.split('|'), start=1)])) else '' for line in
    data.splitlines() if str(line.split('|')[-2]).startswith(d)]

(will not be published)
*