列位,近来俺系统地学习了一下shell编程,好家伙,那可不是一般的纷繁琐碎啊,可谓陷阱重重,防不胜防。摸索中,遇到这个页面,总结了Bash编程中的很多陷阱及必要的解决技巧。在这里,结合这本GNU Bash Reference Manual,我有选择地简要地把这些个Pitfalls给您用百姓喜闻乐见的中文展示出来。由于能力有限,我也不是专职的系统管理员,肯定不能详尽地把所有问题都解释清楚,我本人也觉得没有这个必要。仅供参考而已,欢迎指正和补充。

1
2
3
4
5
6
for i in *.mp3
do
    COMMANDS
done
# 单行形式就是for i in *.mp3; do COMMANDS; done
# ;只是起到命令和关键字间的分割符的作用,完全可以用换行符来代替
Tags: .

  不多说,都在代码里了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
int
main(int AC, char **AV)
{
    FILE *fd = fopen("data", "w+");
    fprintf(fd, "%x%c", 0x41, '1');
    fseek(fd, 0, SEEK_SET);
    int n;
    fscanf(fd, "%d", &n);
    fseek(fd, 0, SEEK_SET);
    char s[4];
    int c = fread(s, 1, sizeof(s), fd);
    s[c] = '\0';
    printf("%d, %s\n", n, s);
    fclose(fd);
    return 0;
}
Tags: .

  简单实现了常见的几种内部排序算法,包括冒泡(Bubble),插入(Insert),快速排序(Quick Sort),堆排序(Heap Sort),归并(Merge),希尔排序(Shell Sort),并对这些算法的耗时在伪随机数上进行了简单的测试。
  说明:

  • 没有实现计数、基数排序等线性复杂度的算法;
  • 各算法只是对算法思想的一次简单模拟,没有过多的优化;
  • 各排序主程序接口参数均为整型数组及元素个数;
  • 程序计时使用了glibc的gettimeofday(),因此。。。;
  • 归并排序中,每次调用都申请和释放堆空间,因此比较耗时。可以采用原地归并、使用全局/静态的方法加以优化;
  • 快速排序中,对待排子序列的长度进行的了判断,对短序列进行优先排序可以减小函数的递归深度(而不是次数);
  • 希尔排序中,为了简洁,步长因子统一取做2.2(11/5)。
Tags: ,.

  写程序时,尤其在C/C++程序中,有大量的配对的符号(surrounding):( ), [ ], { }, < > ‘ ‘, ” “,另外标记语言(如XML)更是由无数的配对标记组成:,

. 如果能够快速地处理这些surroundings,就能大大提升编程的效率。
  Vim本身就有这种配对符号的能力,在Vim中这叫做text object,可以使用:h text-objects查看这些text objects。你会发现Vim只能对这些配对符所包含的文本或者整个text object进行删除和修改,却不能对surrounding进行修改,更不能为普通文本添加surrounding。
  既然有这种需求,就肯定会有热心人士努力,来满足这种需求,方便了自己,也方便了整个Vim用户群。Tim Pope同志就为Vim写了这款插件,surround.vim:

This plugin is a tool for dealing with pairs of “surroundings.” Examples of surroundings include parentheses, quotes, and HTML tags. They are closely related to what Vim refers to as |text-objects|. Provided are mappings to allow for removing, changing, and adding surroundings.

Tags: .

  在StackOverflow上面看到的,分析一下下面的代码,对初学者理解什么是堆,什么是栈,对象是如何拷贝的有所帮助。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
typedef struct node
{
      int i;
      struct node *next;
}node;
node getnode(int a)
{
      struct node n;
      n.i=a;
      n.next=NULL;
      return n;
}
Tags: .

  想必您经常使用复制粘贴功能吧,如果你在桌面环境下工作的话。那么您对Ctrl + C与Ctrl + V一定很熟悉了,您可能还经常使用中指按下鼠标的中键来快捷的粘贴。在X中,此两种粘贴方式是有区别的。Ctrl + V之前要有选中和相应的Ctrl + C,而中键之前只需要选中即可,前者使用的是剪切板(Clipboard),后者使用的是选中(Primary Selection)。关于两者细微的区别见这里
  下面要介绍的是一个能够在命令行访问剪切板(或者Selection,下面以“剪切板”概而论之)的工具。你可能知道,所谓剪切板以及复制粘贴这些功能都是X提供的,而不是Linux内核本身。因此,在命令终端访问剪切板就显得不那么简单,不那么显而易见了。

1
2
3
4
#! /bin/bash
content=`xclip -o`
echo $content >>/.wordump.txt
exit 0
Tags: .

  xbindkeys是一个可以全局按键绑定的程序,使用它,你可以方便用自定义的快捷键序列,来启动常用的程序。而且,xbindkeys独立与桌面环境,无论是gnome, KDE还是xfce,都可以使用同一个xbindkeys配置。、
  xbindkeys最新版本是v1.8.3,而ubuntu10.04的源中还是v1.8.2,较旧的版本在修改配置文件后“立即生效”上有bug,最新版本已经修复。
  安装好xbindkeys后,使用下面命令生成默认的配置文件,

1
$ xbindkeys --default > ~/.xbindkeysrc

  生成的配置文件的格式大致是这样的:

Tags: .

  我编写程序至今有35年了,我做了很多关于程序执行速度方面优化的工(一个示例),我也看过其它人做的优化。我发现有两个最基本的优化技术总是被人所忽略。
  注意,这两个技术并不是避免时机不成熟的优化。并不是把冒泡排序变成快速排序(算法优化)。也不是语言或是编译器的优化。也不是把 i*4写成i<<2的优化。   这两个技术是:

  • 使用 一个profiler。
  • 查看程序执行时的汇编码。
Tags: ,.

  在很多C/C++头文件中,你可能会经常看到使用extern “C”{}包含起来的代码。这种语法的存在是为了使C和C++代码能够兼容。兼容?C++对C本来不就是兼容的吗?确实,在语法层面,C++支持几乎所有C语法。但这里的兼容是目标文件或者库级别的兼容,包括两种情况下的兼容。一种是,在C++代码中调用已经存在的C代码写成的库;另一种是,使用C编写代码,而希望这些代码能够使C++可以调用。
  若想继续讨论extern “C”,就不得不提name mangling。
  我们知道,相比C,C++支持函数重载,支持命名空间,支持类以及成员函数。函数重载允许我们声明名字相同参数不同的函数,命名空间(namespace)和类为名字(或者说符号)划分了不同的域使得我们可以在不同域中使用完全相同的名字。而为了实现这种特性,C++就使用了name mangling。即是说,C++编译器在编译C++文件时,把每一个函数名“打乱”成与函数所在域、参数类型、调用约定相关的另外一个名字(因为汇编级别的代码中,所有符号都在同一个域)。由于C中并不存在这些特性,所以通常C编译器并不对符号进行mangling。

Tags: ,.

  那么,C/C++中,哪些地方是顺序点呢?

  • 每个表达式的结束处;
  • 函数调用中,在所有参数求值完成后,函数体开始执行前有一个顺序点,而参数间的逗号处则没有顺序点。所以f(++i, ++i)的行为也是未定义的;
  • 逻辑运算符&&、||还有条件运算符?:的第一个参数末尾处有一个顺序点;
  • 逗号表达式中每一个逗号处有一个顺序点。因此x = (++i, ++i)是有确定行为的;
  • 在每一个完整的变量声明处有一个顺序点,例如int i, j;中逗号和分号处分别有一个顺序点;
  • for循环控制条件中的两个分号处各有一个顺序点。

  那么,现在,这个程序有问题吗?

1
2
3
4
5
6
7
8
9
int
main()
{
    int m = 1, n = 0;
    printf("%d, %d\n", m, n);
    m ^= n ^= m ^= n;
    printf("%d, %d\n", m, n);
    return 0;
}
Tags: ,,.