python和shell脚本实现查看大文件指定区域范围内的文件内容

来源:互联网 发布:食品包装设计软件 编辑:程序博客网 时间:2024/05/17 01:50

1. 功能

   实践中经常有需要查看某个文件(特别是超过1G的大文件)指定区域范围内的文本内容的需求,为此,笔者使用python的原生open、read和write函数实现对指定文件指定范围内的内容重定向到另一文件的功能,需要时结合shell脚本以16进制显示出筛选出来的文件内容。

2. 原理解析

   sub_file:主要使用python原生的open打开指定文件,seek到指定范围的起始位置之后,read出指定范围的文件内容,write到另一文件。由于read函数实现时已对大文件进行缓冲区处理故打开大文件读取时速度适中不会有太多的等待时间。
   show: 主要使用shell脚本来调用sub_file,对sub_file的输出文件读取,使用xxd命令来实现对读取内容的处理以16进制的形式显示。

3. 实现脚本

3.1 sub_file

#!/usr/bin/env python# author: caft# email: caft0505@gmail.com# Filename: sub_file# Function: get a sub_file from the specified fileimport osimport sysimport getoptimport statdef usage():    print 'Usage: get a sub_file from the specified file'    print 'sub_file <-f file_from> <-t file_to> <-o offset> <-l length> [-h help]'def sub_file(file_from, file_to, offset, length):    base = [10, 16]    try:        if isinstance(offset, str):            offset = long(offset, base['0x' in offset])        if isinstance(length, str):            length = long(length, base['0x' in length])    except Exception, err:        print 'error: %s' % str(err)        return -1    rfd = 0    wfd = 1    try:        rfd = os.open(file_from, os.O_RDONLY)        wfd = os.open(file_to, os.O_WRONLY | os.O_CREAT, 0644)        f_stat = os.stat(file_from)        # st_size will be 0 if file_from is a device.        if stat.S_ISREG(f_stat.st_mode):            if f_stat.st_size > 0:                if offset > f_stat.st_size:                    offset = 0                elif offset < 0: # means to get file content from tail.                    offset = f_stat.st_size + offset            length = min(f_stat.st_size - offset, length)        else:            offset = 0            length = 0        os.lseek(rfd, max(offset, 0), 0)        while length > 0:            rlen = min(4096, length)            buf = os.read(rfd, rlen)            assert rlen == os.write(wfd, buf)            length -= rlen    except Exception, err:        print 'error: %s' % str(err)        return -1    finally:        os.close(rfd)        os.close(wfd)    return 0def parse_args(args):    if len(args) == 0:        usage()        sys.exit(0)    opts = ()    file_from = ''    file_to = ''    offset = 0    length = 0    try:        opts, args = getopt.getopt(args, 'f:t:o:l:h')    except getopt.GetoptError, err:        print 'error:', str(err)        sys.exit(-1)    if len(args) > 0 or len(opts) != 4:        usage()        sys.exit(-1)    for option, value in opts:        if option == '-f':            file_from = value        elif option == '-t':            file_to = value        elif option == '-o':            offset = value        elif option == '-l':            length = value        '''elif option == '-h': #unused            usage()            sys.exit(0)'''    return (file_from, file_to, offset, length)if __name__ == '__main__':    ret = sub_file(*parse_args(sys.argv[1:]))    sys.exit(ret)

3.2 show

#!/usr/bin/env sh# author: caft# email: caft0505@gmail.com# Filename: show# Function: show the text in hex from the specified filefunction usage(){    echo 'Usage: show the text in hex from the specified file'    echo 'show <-n file> <-o offset> <-l length> [-h help]'}if [ $# -ne 6 ]then    usage;    exit 0fifile_from=''offset=0length=0while getopts n:o:l:h OPTIONdo    case $OPTION    in        n) file_from=$OPTARG;;        o)  let "offset = $OPTARG" 2>/dev/null            if [ $? -ne 0 ]            then                if [[ "$OPTARG" != "0" && "$OPTARG" != "0x0"                   && "$OPTARG" != "-0" && "$OPTARG" != "-0x0" ]]                then                    echo 'error input:' $OPTARG                    exit -1                fi            fi;;        l)  let "length = $OPTARG" 2>/dev/null            if [ $? -ne 0 ]            then                if [[ "$OPTARG" != "0" && "$OPTARG" != "0x0" ]]                then                    echo 'error input:' $OPTARG                    exit -1                fi            fi;;        h) usage; # unused            exit 0;;        ?) exit -1;;    esacdoneargc=$[ $# + 1 ]if [ $OPTIND != $argc ]then    usage;    exit -1fiif [ $length -eq 0 ]then    exit 0elif [ $length -lt 0 ]then    echo 'error length is negative!'    exit -1fifile_to=".~tmp_for_${file_from////_}" # replace '/' with '_'if [ ! -f $file_to ]then    touch $file_toelse    echo 'error:' \'$file_to\' 'is existed.'    exit -1fisub_file "-f" "$file_from" "-t" "$file_to" "-o" $offset "-l" $lengthif [ $? -eq 0 ]then    xxd $file_tofirm -f $file_to

4. 使用方法

4.1 sub_file的使用


4.2 show的使用

   另外,对于show而言,-o 和 -l 参数均可为一个简单的不含括号计算表达式,但当计算结果为0时,可能会报错,因为计算过程是使用shell中的 let 工具来完成的。

0 0
原创粉丝点击