9–1.文件过滤. 显示一个文件的所有行, 忽略以井号( # )开头的行. 这个字符被用做Python , Perl, Tcl, 等大多脚本文件的注释符号. 附加题: 处理不是第一个字符开头的注释.
去掉以#开头的行比较好办,用startswith函数也行,用string[0]获得第一个字符也行。
麻烦的是如果要去掉行中间的注释,我这里采取用的是正规表达式(RE)方法,代码如下:
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/filter could not be found
给定的文件内容如下(节选自/etc/ipsec.conf文件):
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/cpp2nd/ipsec.conf could not be found
用上述代码过滤后过的的结果是:
$ ./chapter9.py ipsec.conf
version 2.0
config setup
nat_traversal=yes
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
oe=off
protostack=netkey
9–2. 文件访问. 提示输入数字 N 和文件 F, 然后显示文件 F 的前 N 行.
这个题目比较简单,我们用迭代的办法,尽可能减少代码行数
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/lines could not be found
下面是执行的结果
$ ./e9-2.py
pls enter your filename:/etc/hosts
how many lines do you want print:4
127.0.0.1 wgzhao-laptop localhost.localdomain localhost
#127.0.1.1 wgzhao-nb
202.103.67.201 cp1.3yidc.cn cp1
9–3. 文件信息. 提示输入一个文件名, 然后显示这个文本文件的总行数. 题目简单,但是我们用尽可能短的代码实现
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/file could not be found
我们以/etc/hosts文件为例,程序执行的结果如下:
$ ./chapter9.py
pls enter your file:/etc/hosts
71 /etc/hosts
$ wc -l /etc/hosts
71 /etc/hosts
后面用wc命令来验证我们程序的正确性
9–4.文件访问. 写一个逐页显示文本文件的程序. 提示输入一个文件名, 每次显示文本文件的 25 行, 暂停并向用户提示”按任意键继续.”, 按键后继续执行.
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/cpp2nd/e9-4.py could not be found
我们还是以/etc/hosts文件为测试文件,执行结果如下(为节省页面,输出有省略):
$ ./e9-4.py
127.0.0.1 wgzhao-laptop localhost.localdomain localhost
#127.0.1.1 wgzhao-nb
.....
#test os
172.16.86.125 post3
172.16.86.124 post4
172.16.86.210 dc4
#hk-server
219.90.126.44 hk-server
#test domain
Press any key to continue...
127.0.0.1 bolebi.xplore.cn tea-test.xplore.cn
....
#testing
#68.168.17.9 blog.wgzhao.com
9–6. 文件比较. 写一个比较两个文本文件的程序. 如果不同, 给出第一个不同处的行号和列
这个题目看上去比较简单,但是实现起来总是觉得别扭,找不到一个比较好的算法。我甚至下载了diff程序源代码来看,结果看得一头雾水(唉,我的C语言,是个杯具)
最开始是想每次读取一行,如果这行不同,那就只要比较这行在某个列不同就好了。但是实际编写的时候,发现很难控制判断。最好还是改成了逐自己的比较。这个方法唯一比较麻烦的就似乎你得自己计算是到了哪一行了。判断是如果读取到的是’\n’符号,那就应该换行了,此时行号要加1,当然列号就要重置了,因为新起一行比较了。
第一次使用while..else这种其他语言里没有的语句,感觉很好,少了很多判断。 下面是实现的代码
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/diff could not be found
下面是一些代码实际运行的例子。t1,t2是待比较的两个文件。
$cat t1
onetwo
$cat t2
onb
$./chapter9.py
first different at (row,line) = (1,3)
$cat t1
one
two
$cat t2
one
two
t
$./chapter9.py
first different at (row,line) = (3,1)
$cat t1
one
two
$cat t2
one
two
$./chapter9.py
same file
9–16.文本处理. 人们输入的文字常常超过屏幕的最大宽度. 编写一个程序, 在一个文本文件中查找长度大于 80 个字符的文本行. 从最接近80 个字符的单词断行, 把剩余文件插入到下一行处.程序执行完毕后, 应该没有超过 80 个字符的文本行了.
下面是代码实现
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/file could not be found
9–19.创建文件. 创建前一个问题的辅助程序. 创建一个随机字节的二进制数据文件, 但某一特定字节会在文件中出现指定的次数. 该程序接受三个参数: 1) 一个字节值( 0 - 255 ),
2) 该字符在数据文件中出现的次数, 以及
3) 数据文件的总字节长度.
你的工作就是生成这个文件, 把给定的字节随机散布在文件里, 并且要求保证给定字符在文件中只出现指定的次数, 文件应精确地达到要求的长度.
假定要插入的字节值是byte,出现的次数是cnt,文件大小是filesize。那么,首先创建一个长度为filesize - cnt 的随机数列表(slist)。同时将该数转为字符(chr)。如果随机选出的字节值和byte相同,则跳过(也可以不跳过,修改cnt值)接下来就是吧cnt个byte随机插入到列表里。
我们采取每次随机获得(0,len(slist))之间的某个值,当作slist插入的位置,然后将byte插入。
最后将slist写入文件。
代码如下:
File /Users/wgzhao/Sites/blog.wgzhao.com/source/downloads/code/cpp2nd/e9-19.py could not be found
演示如下:
$ ./chapter9.py 45 3 100
$ ls -l /tmp/test
-rw-r--r-- 1 wgzhao wgzhao 100 2010-06-05 14:35 /tmp/test