您的位置:首页 > 运维架构 > Shell

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

2015-08-01 21:02 951 查看

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 file

import os
import sys
import getopt
import stat

def 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 0

def 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 file

function 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 0
fi

file_from=''
offset=0
length=0
while getopts n:o:l:h OPTION
do
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;;
esac
done

argc=$[ $# + 1 ]

if [ $OPTIND != $argc ]
then
usage;
exit -1
fi

if [ $length -eq 0 ]
then
exit 0
elif [ $length -lt 0 ]
then
echo 'error length is negative!'
exit -1
fi

file_to=".~tmp_for_${file_from////_}" # replace '/' with '_'
if [ ! -f $file_to ]
then
touch $file_to
else
echo 'error:' \'$file_to\' 'is existed.'
exit -1
fi

sub_file "-f" "$file_from" "-t" "$file_to" "-o" $offset "-l" $length

if [ $? -eq 0 ]
then
xxd $file_to
fi

rm -f $file_to

4. 使用方法

4.1 sub_file的使用



4.2 show的使用



   另外,对于show而言,-o 和 -l 参数均可为一个简单的不含括号计算表达式,但当计算结果为0时,可能会报错,因为计算过程是使用shell中的 let 工具来完成的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息