20130704

补充 保持我们最初的理想,当面对无数歧路

补充 保持我们最初的理想,当面对无数歧路

本文继续精略介绍用sed批量修改,补充grep按词匹配。兼极精略讨论周朴园为什么是虚伪的,结论是没文化真可怕。

1. 修正一个错误,find

上文提到 "find ." 中的"."是当前目录,有误。在这里,"."是从当前目录向下递归遍历,而不仅仅是当前目录自己。

如运行:
$ find . -name "*.[h|c]" -exec grep -nH fexecv {} \;
./include/schily.h:107: /* 6th arg not const, fexecv forces av[ac] = NULL */
./include/schily.h:108:extern int fexecv __PR((const char *, FILE *,
FILE *, FILE *, int,
./include/schily.h:110:extern int fexecve __PR((const char *, FILE *,
FILE *, FILE *,
./calltree/calltree.c:232: fexecve (Argv[0], f, fpp[1], stderr,
./libschily/fexec.c:111: ret = fexecv(name, in, out, err, ac, av);
./libschily/fexec.c:168: ret = fexecve(name, in, out, err, av, env);
./libschily/fexec.c:175:fexecv(name, in, out, err, ac, av)
./libschily/fexec.c:182: return (fexecve(name, in, out, err, av, environ));
./libschily/fexec.c:186:fexecve(name, in, out, err, av, env)

搜索到的匹配的文件,全都不在当前目录下,而是在子目录include,lcalltree,libschily中。

2. 去掉杂音 grep找getline

上文中用grep找包含getline的文件,结果有些杂音。

$ find . -name "*.[h|c]" -exec grep -nH getline {} \;
./include/schily.h:117:extern int fgetline __PR((FILE *, char *, int));
./include/schily.h:186:extern int getline __PR((char *, int));
./calltree/calltree.c:852: while (fgetline(fp, fname, sizeof(fname)) >= 0)
./libschily/stdio/fgetline.c:1:/* @(#)fgetline.c 1.6 03/06/15
Copyright 1986, 1996-2003 J. Schilling */
./libschily/stdio/fgetline.c:29:fgetline(f, buf, len)
./libschily/stdio/fgetline.c:67:getline(buf, len)
./libschily/stdio/fgetline.c:71: return (fgetline(stdin, buf, len));

其中有5行不是我们想要的,是因为 fgetline 误伤到的。fgetline比我们要找的多个f。

这些杂音会干扰我们的视线,让我们迷失方向,忘掉最初的理想。解决的方法就是:忽略它们,想办法不去注意它们,让噪音消失。

如果你的意志不够坚强,我们可以借助工具,像下面这样,用"单词"匹配,就把 fgetline 这样的去掉了,同时保留 "getline(" 这样的:
$ find . -name "*.[h|c]" -exec grep -w -nH getline {} \;
./include/schily.h:186:extern int getline __PR((char *, int));
./libschily/stdio/fgetline.c:67:getline(buf, len)

上面多的"-w"参数,代表:

$ grep --help | grep \-w -w -w, --word-regexp force PATTERN to match
only whole words

3. sed的使用,批量修改

上文还提到,找到包含getline字样的文件,然后依次用文本编辑器打开,一个个修改。这样还是容易错,在这些细节中,我们也容易迷失理想。而保持理想的秘诀正是忽略现在。

我们可以用sed批量修改。

(1) 先验证一下修改策略。做批处理的计划最怕的是中间某个步骤做了,但这不是放弃使用批量的理由,我们可以在此处加观察验证。

$ find . -name "*.[h|c]" -exec sed 's/\<getline\>/getline_calltree/'
{} \; | grep getline
extern int fgetline __PR((FILE *, char *, int));
extern int getline_calltree __PR((char *, int));
while (fgetline(fp, fname, sizeof(fname)) >= 0)
/* @(#)fgetline.c 1.6 03/06/15 Copyright 1986, 1996-2003 J. Schilling */
fgetline(f, buf, len)
getline_calltree(buf, len)
return (fgetline(stdin, buf, len));

还是用find找到*.h和*.c文件,然后调用 sed 批量修改。

sed的意思是 stream editor,可以执行对文本的编辑命令。这些命令在命令行里给出,不仅跟IDE这样的图形界面不一样,甚至跟emacs/vi这样的全屏编辑也不一样。不知道sed和行编辑哪一个更早。

我们来看一下sed的这些参数。"sed 's/\<getline\>/getline_calltree/' {} "

's/\<getline\>/getline_calltree/'就是编辑的命令,它的意思是:查找 (search,
s)符合条件的文字"\<getline\>",改成"getline_calltree"。格式是"s/匹配条件/修改成什么样子"。

匹配条件"\<getline\>"中的"\<"和"\>"表示按词匹配,类似于grep中的-w。"\"是转义符,因为"<"">"是特殊字符。

所以sed这部分的作用是找到 (*.h和*.c中的)所有getline这样的整词,修改为getline_calltree。

上述命令行最后的 grep getline,是为了检验修改策略是正确的。我们观察结果,果然,所有的getline都变成了getline_calltree,而fgetline无一误伤。

(2) 实施
执行
$ find . -name "*.[h|c]" -exec sed -i 's/\<getline\>/getline_calltree/' {} \;

这里的"-i"参数的意思是:

-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if extension supplied)

(3) 验证

保险起见,可以再看看"-i"到底改了没有。

$ find . -name "*.[h|c]" -exec grep -w -nH getline {} \;
$

果然干干净净的了。

(4) 剩下的工作

然后呢?

find . -name "*.[h|c]" -exec sed -i 's/\<fexecve\>/fexecve_calltree/' {} \;

然后 make。

然后看看编译出来的东西 (object) 在哪里。

$ find . -name calltree
./calltree
./calltree/OBJ/i686-linux-cc/calltree

大功告成。

(5) 批量

这样,当你告诉别人如何修改 calltree
才能编译的时候,你不必写上一大篇"先找到什么,在哪几个文件里,再找什么,在哪几个文件里"。你可以提供一个脚本完成这个任务。

如下:
find . -name "*.[h|c]" -exec sed -i 's/\<getline\>/getline_calltree/' {} \;
find . -name "*.[h|c]" -exec sed -i 's/\<fexecve\>/fexecve_calltree/' {} \;

这两行里蕴含了上述所有要求的步骤。

科幻小说作家Ted姜曾经写过一个情节,两个智商非常高的牛人终于碰面,他们只说了一个字,里面就包含了千言万语,进行了猩猩相惜还有战争。牛人们之所以能进行这种对话的原因在于,话语中的每个词都包含了非常的丰富的约定了确定定义的信息。因为那些是已经知道的了,正如康德说的,分析得到的都不是知识,而综合的,把这些已知知识放在一起的微量的未知,才是知识。调用DLL的程序之所以那么短,就是因为很多动作流程的约定已经在DLL中了。

周朴园之所以可以定性为虚伪的原因,也在于他实施了具有精确约定含义的动作--没有娶四凤她妈,剩下的说啥也白扯。他的各种小动作只是用来表现自己具有何处情怀和愿望而已,于四凤她妈没有任何影响。正是周的这种又做坏事,又要表现自己是好人的的做法,可以性定他为虚伪。所以,有确切含义的约定的知识在判断中至关重要。所有某个知识的背后庞大的网络支撑和构成了这个知识本身。

所以说,没文化真可怕。

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

No comments: