HICK 者,乡巴佬也

shell/命令行下的光标移动等æ“作快æ·é”®

Posted in: Linux/Unix工具 — Hick @ 2008/12/27 14:54:15 Comments (1)

shell 命令行下ä¸å°‘键盘æ“作跟 Emacs 是类似的,å¯èƒ½ä¸èƒ½è¯´æ˜¯ä»Ž Emacs 借鉴过æ¥çš„,这些快æ·çš„ä½¿ç”¨ï¼Œè°æ—©è°æ™šè¿˜ä¸å¥½è€ƒè¯ï¼Œä¸è¿‡æ€è·¯æ˜¯ä¸€è‡´çš„ã€‚ä¹‹å‰æŸæ¬¡çªç„¶æ¥åŠ²è¯•äº† C-a C-e 等,刚æœç´¢å¹¶å®žè·µäº†è‹¥å¹²æ“作,在 SecureCRT 登录 suse 的环境验è¯äº†ï¼Œæ•´ç†å¦‚下(ä¸ä¸€å®šæ˜¯æ‰€æœ‰ shell 都支æŒ):

(注æ„下é¢çš„”剔都是指”å·¦”或”上”,”厔是”峔或”下”)

C-r æŸ¥æ‰¾åŽ†å²æ‰§è¡Œå‘½ä»¤ï¼Œå¾ˆä¾¿æ·çš„调用历å²å‘½ä»¤çš„æ–¹å¼ï¼Œè¾“入历å²å‘½ä»¤å…³é”®å­—ï¼Œå°±ä¼šåŠæ—¶æ˜¾ç¤ºåŒ¹é…命令,enter å³å¯æ‰§è¡Œ
C-p å‰ä¸€æ¡æŒ‡ä»¤
C-n åŽä¸€æ¡æŒ‡ä»¤
C-c 终止已ç»è¿è¡Œçš„命令(针对还没有è¿è¡Œå®Œçš„命令和脚本,实际为å‘相关进程å‘é€ä¸­æ–­ä¿¡å·)æˆ–è€…å–æ¶ˆå·²ç»è¾“入的命令
C-o/C-j/C-m 执行当å‰è¡Œè¾“入的命令,跟 enter 类似
C-l 清å±ï¼Œclear 命令

C-a 移动光标到行首
C-e 移动光标到行尾

C-t 交æ¢å…‰æ ‡å‰ä¿©å­—符的ä½ç½®
C-h å¾€åŽåˆ é™¤ä¸€å­—符
C-d å¾€å‰åˆ é™¤ä¸€å­—符
C-b å¾€åŽç§»åŠ¨ä¸€ä¸ªå­—ç¬¦
C-f å¾€å‰ç§»åŠ¨ä¸€ä¸ªå­—ç¬¦

下é¢å‡ ä¸ªæ“作原ç†ä¼°è®¡ç±»ä¼¼ emacs çš„ yank æ“作,å¯ä»¥ç†è§£ä¸ºä¸€å¥—ç‹¬ç«‹çš„ç²˜è´´æ¿æœºåˆ¶:
C-w 剪切å‰ä¸€ä¸ªå•è¯(空格间隔的字符串å•å…ƒ)
C-u 剪切到行首
C-k 剪切到行尾
C-y 粘贴剪切

文件æ“作3(Beginning Linux Programming 笔记6)

Posted in: Linux 编程 — Hick @ 2008/12/16 23:20:44 Comments (0)

原文地å€: http://www.hickwu.com/?p=263
作者: Hick
转载请注明出处

p139 å…¶ä»–ç®¡ç†æ–‡ä»¶çš„系统调用

lseek 打开文件以åŽè¯»å–时,有一个文件指针的概念,文件指针决定 read 函数读å–字符的开始ä½ç½®ï¼Œlseek 函数用æ¥ç§»åŠ¨æ–‡ä»¶æŒ‡é’ˆã€‚

#include <unistd.h>
#include <sys/types.h>
off_t lseek(int fildes, off_t offset, int whence);

offset 为移动的的具体数é‡ï¼Œwhence 决定移动的方å¼ï¼ŒSEEK_SET 表示为ç»å¯¹ä½ç½®ï¼›SEEK_CUR è¡¨ç¤ºç›¸å¯¹å½“å‰æŒ‡é’ˆçš„ä½ç½®ï¼›SEEK_END 表示相对文件末尾 ,移动失败返回 -1 。

有一系列的函数用æ¥è¿”回文件的信æ¯ï¼š fstat, stat, lstat 返回æè¿°æ–‡ä»¶ä¿¡æ¯çš„一个结构(structure),ä¸åŒçš„æ˜¯ fstat 以 fd ä¸ºå‚æ•°ï¼Œè€Œ stat å’Œ lstat ä»¥æ–‡ä»¶è·¯å¾„ä¸ºå‚æ•°ã€‚lstat 相比 stat çš„ä¸åŒæ˜¯ï¼Œå½“文件是一个 link 时,该函数返回的是 link 的信æ¯è€Œä¸æ˜¯ link æŒ‡å‘æ–‡ä»¶çš„ä¿¡æ¯:

#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int fstat(int fildes, struct stat *buf);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);

在ä¸åŒçš„系统下返回的文件信æ¯ç»“æž„å¯èƒ½ä¸ä¸€æ ·ï¼Œä¸è¿‡ä¸€èˆ¬åŒ…å«ä»¥ä¸‹ä¸€äº›æˆå‘˜ï¼š

- st_mode 文件æƒé™å’Œæ–‡ä»¶ç±»åž‹ä¿¡æ¯(目录ã€ä¸€èˆ¬æ–‡ä»¶ã€link ç­‰)
- st_ino 文件相关的节点 inode ä¿¡æ¯
- st_dev 文件所在的设备
- st_nlink 文件的硬连接数

å¦å¤–还有文件的所属拥护以åŠç¾¤ç»„ã€è®¿é—®æ—¶é—´ç­‰ä¿¡æ¯ï¼Œä¸ä¸€ä¸€åˆ—出。 解释下 ctime 为文件的æƒé™ã€æ‰€å±žç”¨æˆ·æˆ–群组以åŠå†…å®¹çš„æ”¹å˜æ—¶é—´ï¼›mtime 为内容的最åŽä¿®æ”¹æ—¶é—´ã€‚

有一些å®å¯ä»¥ç”¨æ¥æ£€æŸ¥æ–‡ä»¶ç±»åž‹ä¿¡æ¯ï¼š

- S_ISBLK æ£€æŸ¥æ˜¯å¦æ˜¯å—设备文件
- S_ISCHR æ£€æŸ¥æ˜¯å¦æ˜¯å­—符设备文件
- S_ISDIR æ£€æŸ¥æ˜¯å¦æ˜¯ç›®å½•文件
- S_ISFIFO æ˜¯å¦æ˜¯ FIFO
- S_ISREG 常规文件
- S_ISLNK link 符å·

示范:

struct stat statbuf;
mode_t modes;
stat(“filenameâ€,&statbuf);
modes = statbuf.st_mode;
if(!S_ISDIR(modes) && (modes & S_IRWXU) == S_IXUSR)

p141 dup å’Œ dup2 用æ¥å¤åˆ¶ fd ,实现多个 fd 指å‘åŒä¸€ä¸ªæ–‡ä»¶ã€‚dup 接收一个 fd 傿•°ï¼Œè¿”回一个新的 fd ï¼›dup2 æŽ¥æ”¶ä¸¤ä¸ªå‚æ•°ï¼Œèƒ½å¤Ÿé«˜æ•ˆçš„æŠŠä¸€ä¸ª fd å¤åˆ¶åˆ°å¦å¤–一个 fd 。在多进程处ç†ç¨‹åºä¸­ï¼Œè¿™ä¸¤ä¸ªå‡½æ•°ä¼šéžå¸¸æœ‰ç”¨ï¼ŒåŽè¾¹çš„章节会涉åŠã€‚

p142 标准 io 库 使用标准 io 库需è¦åŒ…å«å¤´æ–‡ä»¶ stdio.h 。跟系统调用类似,标准库æ“作文件也需è¦å…ˆæ‰“开一个文件,stream 作为 fd 的标准库版,用æ¥è¡¨ç¤ºä¸€ä¸ªæ‰“开的文件。stream 是用指针实现的,指å‘åŒ…å«æ–‡ä»¶ä¿¡æ¯çš„一个结构: FILE * 。

系统å¯åŠ¨ä¸€ä¸ªè¿›ç¨‹çš„æ—¶å€™ä¼šæ‰“å¼€ä¸‰ä¸ªæ–‡ä»¶ï¼š stdin, stdout, stderr ,也就是对应系统调用中涉åŠçš„三个 fd: 0, 1, 2 。

p143 fopen 是模拟系统调用 open 的库函数,一般åªå»ºè®®ç”¨æ¥åšä¸€èˆ¬çš„æ–‡ä»¶ä»¥åŠæ ‡å‡†è¾“入输出æ“作。其他 linux 文件的æ“作建议用系统调用或者其他库。 fopen 的函数原型:

#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);

mode 的相关å–值说明(上é¢çš„ b 都是表示二进制文件):

- r/rb åªè¯»æ–¹å¼æ‰“å¼€
- w/wb å†™æ–¹å¼æ‰“开,并把文件截为空
- a/ab è¿½åŠ å†™æ–¹å¼æ‰“å¼€
- r+/rb+ è¯»å†™æ–¹å¼æ‰“å¼€
- w+/wb+ è¯»å†™æ–¹å¼æ‰“开并把文件截为空
- a+/ab+ è¯»å†™æ–¹å¼æ‰“开,写文件追加到文件末尾

æ³¨æ„ c è¯­è¨€é‡ŒåŒæ ·ä¸€ä¸ªå­—æ¯ï¼Œå¯ä»¥æ˜¯å­—符串也å¯ä»¥æ˜¯å­—符,这里的 mode è¦æ±‚是字符串。跟 fd 一样,打开的 stream 也有数é‡é™åˆ¶ï¼Œå…·ä½“是通过 stdio.h 中定义的 FOPEN_MAX æ¥å†³å®šçš„。

fread æŒ‰ç…§æŒ‡å®šé•¿åº¦è¯»å–æ–‡ä»¶:

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

从指定的 stream ä¸­è¯»å– niterms 个大å°ä¸º size 的数æ®è®°å½•,返回æ“作æˆåŠŸçš„è®°å½•æ•° — 注æ„䏿˜¯ read å‡½æ•°çš„è¿”å›žè¯»å–æˆåŠŸçš„å­—èŠ‚æ•°ï¼Œè¯»å–到的字符串ä¿å­˜åˆ° ptr 中。

fwrite 跟 fread 类似:

#include <stdio.h>
size_t fwrite (const void *ptr, size_t size, size_t nitems, FILE *stream);

fclose 用æ¥å…³é—­ä¸€ä¸ª stream, 因为 io 有 buffer, 所以关闭 fd 之å‰ï¼Œ buffer 中没有写入文件的数æ®ä¼šè¢«å†™è¿›åŽ»ã€‚ä¸€èˆ¬æ¥è¯´ï¼Œå³ä½¿ä¸æ˜¾å¼çš„ fclose æ–‡ä»¶ï¼Œç¨‹åºæ‰§è¡Œå®Œæ¯•以åŽä¹Ÿä¼šå…³é—­ç›¸å…³ stream ,当然ä¸èƒ½å¤Ÿä¾èµ–这样的自动处ç†ã€‚

p144 fflush å‡½æ•°ç”¨æ¥æŠŠ buffer 的修改应用到文件上,实际上 fclose 之å‰ä¼šè‡ªåŠ¨è°ƒç”¨è¯¥å‡½æ•°ï¼Œæ‰€ä»¥å¦‚æžœæ²¡æœ‰ç‰¹æ®Šå¿…è¦ï¼Œä¸éœ€è¦æ˜¾å¼è°ƒç”¨ fflush 。

p145 fseek 跟系统调用 lseek 类似,而且ä¸è·Ÿ fread å’Œ fwrite 一样是以数æ®è®°å½•为æ“作å•元。跟 lseek 的主è¦ä¸åŒæ˜¯ lseek 返回实际的åç§»é‡ï¼Œè€Œ fseek æ“作æˆåŠŸæ—¶è¿”å›ž 0 ,失败返回 -1 。

è¿˜æœ‰ä¸‰ä¸ªè¯»å– stream ä¿¡æ¯ä¸­çš„æ•°æ®çš„函数 fgetc, getc, getchar 。fgetc 获得 stream 的下一个字符串,如果读到了文件末尾或者å‘生错误,则返回 EOF ,这时候需è¦é€šè¿‡ ferror å’Œ feof æ¥åŒºåˆ†å…·ä½“是哪中错。

#include <stdio.h>
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar();

getc 函数跟 fgetc 效果一样,åªä¸è¿‡ä»–å¯èƒ½æ˜¯ç”¨å®å®šä¹‰å®žçŽ°çš„ï¼Œä¹Ÿå°±æ˜¯æŸäº›ç³»ç»Ÿä¸‹å¯èƒ½æ˜¯ä¸€ä¸ªå®ã€‚(具体细节ä¸å¤§æ¸…楚) getchar ä¸éœ€è¦å‚数,而是直接从标准输入设备从读å–一个字符。

跟上é¢è¯»å–函数想对应,有写入的系列函数 fputc, putc å’Œ putchar 。他们都返回实际写入的字符,如果失败则返回 EOF ã€‚æ³¨æ„ putchar çš„å‚æ•°åªèƒ½å¤Ÿæ˜¯æ•´æ•°è€Œä¸æ˜¯å­—符,这跟 getchar 的的返回值是一样。正是这样,æ‰ä½¿å¾— EOF 的值å¯ä»¥æ˜¯ -1 — 在 char 里,没有对应字符。

p146 å‰é¢çš„ fgetc 是按照字符æ¥è¯»åŽ»ï¼Œè¿˜æœ‰ä¸¤ä¸ªå‡½æ•° fgets å’Œ gets å¯ä»¥æŒ‰ç…§å­—符串æ¥è¯»å–。

#include <stdio.h>
char *fgets(char *s, int n, FILE *stream);
char *gets(char *s);

fgets 函数从 stream ä¸­è¯»å– n -1 个字符或者读到一行结æŸ(包括文件末尾)。读å–到 n - 1 个字符以åŽï¼Œä¼šè‡ªåŠ¨è¿½åŠ ä¸€ä¸ª \0 ,表示读å–到的是一个字符串。最终返回 s 的长度为 n 。fgets 执行æˆåŠŸåˆ™è¿”å›žå‚æ•° s 的指针,达到文件末尾或者出错时都返回空指针(null pointer),出错时还会把错误设置写到 errno ,还有å¥è¯æ²¡æ‰“明白:If the stream is at the end of a file, it sets the EOF indicator for the stream and fgets returns a null pointer. 没弄懂怎么标记这个 EOF 的。

gets 函数的ä¸åŒæ˜¯ä»–从标准输入设备读å–å­—ç¬¦ã€‚éœ€è¦æ³¨æ„的是 gets 函数并ä¸é™åˆ¶è¾“入的字符串大å°ï¼Œè¿™å®¹æ˜“引起问题,一般尽é‡é¿å…使用 gets 而使用 fgets 。

æ ¼å¼åŒ–输入和输出 printf, fprintf, sprintf 都是格å¼åŒ–输出数æ®çš„函数。printf 输出到标准输出设备,fprintf è¾“å‡ºåˆ°å‚æ•°æŒ‡å®šçš„ stream ,sptinf è¾“å‡ºåˆ°å‚æ•°æŒ‡å®šçš„æŒ‡é’ˆ:

#include <stdio.h>
int printf(const char *format, ...);
int sprintf(char *s, const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);

使用 sprintf æ—¶éœ€è¦æ³¨æ„ s éœ€è¦æœ‰è¶³å¤Ÿçš„长度æ¥ä¿å­˜å­—符串。格å¼åŒ–输出的使用 % 为标识字符,格å¼å­—符串中需è¦è¾“出 % çš„è¯éœ€è¦è”系两个 % æ¥è¡¨ç¤ºã€‚常è§çš„æ ¼å¼æœ‰ %d 为整型,%o å’Œ %x 分别为整型的八进制和åå…­ç¦æ­¢è¾“出;$c 为字符;%s 为字符串; %f 为浮点型数æ®ã€‚上é¢éƒ½æ˜¯æ¯”较简å•的常è§ç”¨æ³•,通常都å¯ä»¥å¸¦ä¸€äº›ä¿®é¥°ç¬¦ã€‚比如浮点数å¯ä»¥é€šè¿‡ %f2.3 æ¥å®šä¹‰å°æ•°ç‚¹ç­‰ã€‚而字符的输出控制也å¯ä»¥æœ‰ä¿®é¥°ç¬¦ï¼š

%10s    "Hello"                 |          Hello|
%-10s   "Hello"                 |Hello          |
%10d    1234                    |           1234|
%-10d   1234                    |1234           |
%010d   1234                    |0000001234     |
%10.4f  12.34                   |        12.3400|
%10s    "HelloTherePeeps"       |HelloTherePeeps|

æ³¨æ„æ ¹æ® POSIX 规范,输出ä¸ä¼šè‡ªåŠ¨æˆªå–字符串长度,所以上é¢çš„æœ€å¥½ä¸€é¡¹èƒ½å¤Ÿè¾“出所有字符串。

p148 跟标准输出函数对应,有 scanf. fscanf, sscanf 三个输入格å¼åŒ–函数。注æ„因为 scanf ä¸­éœ€è¦æŒ‡å®šè¾“出信æ¯çš„类型,所以到输入的数æ®ç±»åž‹ä¸å¯¹äº‹ï¼Œå¯èƒ½å¼•起内存崩溃(corrupt)。一般æ¥è¯´ï¼Œscanf 系列函数ä¸å»ºè®®ä½¿ç”¨ï¼Œå­˜åœ¨è®¾è®¡ç¼ºé™·ï¼Œä½¿ç”¨ä¸æ–¹ä¾¿å¹¶ä¸”容易导致错误。我们å¯ä»¥ä½¿ç”¨ fread å’Œ fgets æ¥èŽ·å–用户输入信æ¯ã€‚

p149 io 标准库还æä¾›å…¶ä»–函数:

- fgetpos 文件 stream 䏭当剿Œ‡é’ˆçš„ä½ç½®
- fsetpos 设置 stream 中的指针ä½ç½®
- ftell Return the current file offset in a stream(没看出æ¥è·Ÿ fgetpos 的差别)
- rewind é‡è®¾æ–‡ä»¶æŒ‡é’ˆä½ç½®
- freopen å¤ç”¨æ–‡ä»¶ stream
- setvbuf: Set the buffering scheme for a stream
- remove è·Ÿ unlink 类似,ä¸è¿‡è¯¥å‡½æ•°è¿˜å¯ä»¥åˆ é™¤ç›®å½•

由于使用标准 io 库时å¯ä»¥åˆ©ç”¨å…¶ç¼“å†²åŠŸèƒ½ï¼ŒåŒæ ·æ˜¯é€ä¸ªå­—ç¬¦æ‹·è´æ–‡ä»¶å†…容,用 io 库比调用系统 io è¦å¿«å¾ˆå¤šã€‚

文件æ“作2(Beginning Linux Programming 笔记5)

Posted in: Linux 编程 — Hick @ 2008/12/13 8:57:29 Comments (0)

原文地å€: http://www.hickwu.com/?p=262
作者: Hick
转载请注明出处

p131 linux 中对打开的文件都用一个整型值æ¥è¡¨ç¤ºï¼Œä¹Ÿå°±æ˜¯æ–‡ä»¶æè¿°ç¬¦ï¼š file descriptor, 也å¯ä»¥ç®€ç§°ä¸º fd 。之å‰çš„ shell 编程中接触过三个最常用且固定值的 fd : 0 为标准输入文件; 1 为标准输出文件; 2 为标准错误文件 。

使用系统调用 write 需è¦åŒ…å« unistd.h ,(ç†è§£ä¸º unix standard),函数原型: size_t write(int fildes, const void *buf, size_t nbytes) ,表示把 buf çš„å‰ nbytes 个字节(æ¢å¥è¯è¯´ï¼Œæœ‰è‡ªåŠ¨æˆªå–的功能)写入 fildes 所表示的文件中,函数返回实际写入文件的字符串长度。返回 0 则表示没有写入任何字符,-1 表示å‘生错误,这时候å¯ä»¥ä»Žå…¨å±€å˜é‡ errno 中获得错误编ç ã€‚ 䏋颿˜¯ä¸€ä¸ªä½¿ç”¨ä¾‹å­:

#include <unistd.h>
#include <stdlib.h>

int main()
{
    if ((write(1, "Here is some data\n", 18)) != 18)
        write(2, "A write error has occurred on file descriptor 1\n",46);
    exit(0);
}

éœ€è¦æ³¨æ„,实际写入的文件数å¯èƒ½è·ŸæŒ‡å®šçš„字符长度(å³ä½¿å­—符足够长)å¯èƒ½ä¸ä¸€æ ·ï¼Œè¿™æ—¶å€™éœ€è¦æ£€æŸ¥ errno ï¼Œç„¶åŽæŠŠå‰©ä½™æ²¡æœ‰å†™å…¥çš„éƒ¨åˆ†ç»§ç»­å†™å…¥ã€‚æ–‡ä¸­æ²¡æœ‰ç»™å‡ºå…·ä½“æ“作方法。

p132 è·Ÿ write 类似需è¦åŒ…å« unistd.h 头文件,函数原型: size_t read(int fildes, void *buf, size_t nbytes) ,表示从 fildes è¡¨ç¤ºçš„æ–‡ä»¶ä¸­è¯»å– nbytes 个字节,并把读å–到的数æ®ä¿å­˜åˆ°æŒ‡é’ˆ buf 。如果返回 0 表示什么也没有读到,一般是已ç»è¯»åˆ°äº†æ–‡ä»¶æœ«å°¾ã€‚返回 -1 表示产生了错误,错误编ç ä¿¡æ¯ä¿å­˜åœ¨çŽ¯å¢ƒå˜é‡ errno 中(这是系统调用出错的通用规则,没有特殊说明就按此处ç†ï¼ŒåŽé¢ä¸å†è¯¦è¿°)。

两ç§å‘½ä»¤äº¤äº’输入的方å¼ï¼Œç¬¬ä¸€ç§åˆ©ç”¨ç®¡é“,第二ç§åˆ©ç”¨è¾“å…¥é‡å®šå‘:

echo hello there | ./simple_read
 ./simple_read < draft1.txt

p133 使用 open 系统调用需è¦åŒ…å«çš„头文件有三个 fcntl.h, sys/types.h å’Œ sys/stat.h 。严格æ„义上说按照 POSIX 标准ä¸éœ€è¦åŒ…å«åŽé¢ä¸¤ä¸ªæ–‡ä»¶ï¼Œä½†æ˜¯åœ¨ä¸ªåˆ« UNIX 环境å¯èƒ½ä¼šæœ‰é—®é¢˜ã€‚open 函数的原型: int open(const char *path, int oflags, mode_t mode) 。open 函数打开文件路径为 path 的文件,返回文件的 fd 的整数,fd 是进程范围的,进程之间ä¸å¯ä»¥å…±äº« fd ,ä¸åŒçš„进程打开åŒä¸€ä¸ªæ–‡ä»¶å¾—到的 fd 一般ä¸ä¼šç›¸åŒã€‚å¦‚æžœä¸¤ä¸ªè¿›ç¨‹åŒæ—¶å‘一个文件写数æ®ï¼Œä»–们并ä¸ä¼šäº¤é”™åœ¨ä¸€èµ·ï¼Œå…¶ä¸­çš„一个数æ®ä¼šè¦†ç›–å¦å¤–一个的数æ®ï¼Œä¸€èˆ¬é€šè¿‡åŽé¢è¯´çš„æ–‡ä»¶é”æ¥è§£å†³è¿™ç§é—®é¢˜ã€‚

oflags 表示打开文件的一些访问模å¼ç­‰æŽ§åˆ¶é€‰é¡¹ã€‚常用的选项: O_RDONLY åªè¯»; O_WRONLY åªå†™; O_RDWR åŒæ—¶è¯»å†™ã€‚ 一般也å¯ä»¥äºŽä»¥ä¸‹é€‰é¡¹åšä½è¿ç®—:O_APPEND 把数æ®å†™åœ¨æ–‡ä»¶æœ«å°¾, O_TRUNC 清空文件内容; O_CREAT 如果文件ä¸å­˜åœ¨åˆ™åˆ›å»ºæ–‡ä»¶ï¼Œä¸€èˆ¬éœ€è¦æŒ‡å®šæ–‡ä»¶æƒé™çš„ mode 值; O_EXCL 排他的创建文件,一般和 O_CREAT 一起使用,ä¿è¯å¤šä¸ªè¿›ç¨‹åŒæ—¶ open 时优先创建。用 man 2 open 命令å¯ä»¥æŸ¥çœ‹æ›´çš„ open 函数说明。

打开文件æˆåŠŸæ—¶è¿”å›ž fd ,å¦åˆ™è¿”回 -1 。打开文件的 fd 值有一个规则:它总是å–当å‰è¿›ç¨‹å·²æ‰“开的 fd å¯å–的最å°å€¼ã€‚有一个éžå¸¸æœ‰ç”¨çš„æŠ€å·§ï¼Œå½“我们关闭标准的输出 fd 也就是 1 æ—¶ï¼Œå† open 一个文件其 fd 就是 1 ,它ä¾ç„¶è¢«å½“åšæ˜¯æ ‡å‡†è¾“出设备,但是已ç»è¢«å·æ¢æ¢æŸ±ã€‚

å¦å¤–一个ä¸å¸¸ç”¨çš„类似 open 的系统调用为 create ,ä¸ä½œæ·±å…¥ä»‹ç»ã€‚一个è¿è¡Œçš„进程能够打开的 fd 值都是有é™åˆ¶çš„,一般现在的 linux 系统都是 1024 个。在 c 里通过在 limit.h 中定义 OPEN_MAX 叏釿¥æŒ‡å®šçš„。

p134 åˆå§‹æƒé™ 当 open 函数使用 O_CREAT æ ‡è®°æ—¶ï¼Œéœ€è¦æŒ‡å®šåˆ›å»ºæ–‡ä»¶çš„æƒé™ä¿¡æ¯ï¼Œé€šå¸¸éƒ½æ˜¯è¿™äº›æƒé™ä¿¡æ¯çš„ä½è¿ç®—ç»“æžœä½œä¸ºå‚æ•°:

- S_IRUSR 所有者的读æƒé™
- S_IWUSR 所有ç€çš„写æƒé™
- S_IXUSR 所有者的执行æƒé™
- S_IRGRP 组用户的读æƒé™
- S_IWGRP 组用户写æƒé™
- S_IXGRP 组用户执行æƒé™
- S_IROTH 其他用户读æƒé™
- S_IWOTH 其他用户写æƒé™
- S_IXOTH 其他用户执行æƒé™

需è¦åˆ›å»ºçš„æ–‡ä»¶ä¸º 所有者有读æƒé™ï¼Œå…¶ä»–用户有执行æƒé™:

open (“myfileâ€, O_CREAT, S_IRUSR|S_IXOTH);

éœ€è¦æ³¨æ„的是,这些æƒé™åªé’ˆå¯¹æ–°åˆ›å»ºçš„æ–‡ä»¶è€Œè¨€ï¼Œå¹¶ä¸æ˜¯æŒ‡å®š O_CREAT 就会创建文件的。å¦å¤–,用户的 mask (shell 下的 umask 命令å¯ä»¥æ”¹å˜å…¶å€¼)ä¹Ÿä¼šå½±å“æ‰€åˆ›å»ºæ–‡ä»¶çš„æƒé™ã€‚

p135 umask 是一个决定新创建的文件的æƒé™çš„系统å˜é‡ã€‚读ã€å†™ã€æ‰§è¡Œåˆ†åˆ«ä¸º 4ã€2ã€1 ,这三个的任何一个组åˆçš„å’Œå€¼ä»£è¡¨ä¸€ç§æƒé™ï¼Œä¸‰ä¸ªå’Œå€¼æ”¾åœ¨ä¸€èµ·ç»„æˆ umask,分别定义所有者ã€ç»„用户ã€å…¶ä»–用户ä¸å…许拥有的æƒé™ï¼Œæ¯”如 777 表示这三ç§ç”¨æˆ·éƒ½ä¸èƒ½å¤Ÿæœ‰è¯»å†™æ‰§è¡Œæƒé™ã€‚ 022 组用户和其他用户都ä¸èƒ½å¤Ÿæœ‰å†™æƒé™ã€‚ 当用户 open + OCREAT 创建一个文件的时候,系统会对比 open 函数指定的æƒé™å’Œ umask 值,并且以 umask 值指定的æƒé™ä¸ºå…ˆã€‚

close 函数没有什么特别的,以 fd ä¸ºå‚æ•°ï¼Œå…³é—­æ–‡ä»¶ã€‚å½“ç„¶ï¼Œä¸€èˆ¬æˆ‘ä»¬éœ€è¦æ³¨æ„检查该函数返回值为 0 ,表示关闭æˆåŠŸï¼Œè¿”å›žä¸º -1 è¡¨ç¤ºå‡ºé”™ï¼Œå»ºè®®è¯»å– errno å˜é‡å€¼ã€‚

p137 ioctl 为å‘硬件å‘é€ç‰¹æ®Šçš„æŽ§åˆ¶æŒ‡ä»¤ï¼Œç»ˆç«¯ã€socket 以åŠç£å¸¦æœºç­‰éƒ½æœ‰è¿™æ ·çš„æŒ‡ä»¤åŽ»æŽ§åˆ¶ç¡¬ä»¶çš„è¡Œä¸ºã€‚æ¯”å¦‚ä¸‹é¢çš„æŒ‡ä»¤ç”¨æ¥å‘Šè¯‰ç¡¬ç›˜æ‰“开键盘的 LED ç¯ï¼š

ioctl(tty_fd, KDSETLED, LED_NUM|LED_CAP|LED_SCR);

# function prototype
#include <unistd.h>
int ioctl(int fildes, int cmd, ...);

䏋颿˜¯ä¸€ä¸ªæŒ‰å­—ç¬¦æ‹·è´æ–‡ä»¶å†…容的应用的主体代ç 

#include <unistd.h>
...
    in = open("file.in", O_RDONLY);
    out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
    while(read(in,&c,1) == 1)
        write(out,&c,1);
...

注æ„一般 unistd.h 都需è¦ç¬¬ä¸€ä¸ªåŒ…å«ã€‚编译åŽè¿è¡Œè¯¥ç¨‹åº TIMEFORMAT=” ” time ./copy_system å¯ä»¥å‘现,这ç§ç¨‹åºç³»ç»Ÿè°ƒç”¨çš„æ¶ˆè€—æ¯”è¾ƒå¤§ã€‚æ³¨æ„ TIMEFORMAT 的值用æ¥è¦†ç›–默认 POSIX 风格的时间格弗默认的风格中也ä¸ä¼šæ˜¾ç¤º CPU æ¶ˆè€—ã€‚ä¸‹é¢æˆ‘们通过å‰é¢ä»‹ç»è¿‡çš„ä¸€æ¬¡è¯»å†™æ¯”è¾ƒå¤šçš„æ•°æ®æ¥å¯¹æ¯”性能:

char block[1024];
int in, out;
int nread;

in = open("file.in", O_RDONLY);
out = open("file.out", O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
while((nread = read(in,block,sizeof(block))) > 0)
    write(out,block,nread);

exit(0);

这里一次读入 1024 个字节也就是 1k ï¼Œé‡æ–°ç¼–译åŽå†è¿è¡Œ TIMEFORMAT=” ” time ./copy_block ,会å‘现性能大大的æé«˜äº†ã€‚

文件æ“作1(Beginning Linux Programming 笔记4)

Posted in: Linux 编程 — Hick @ 2008/12/10 22:34:26 Comments (0)

原文地å€: http://www.hickwu.com/?p=261
作者: Hick
转载请注明出处

p126 æ“作文件的时候我们需è¦ä½¿ç”¨ç›¸å…³çš„系统调用(system call),ä¸è¿‡ä¸€èˆ¬æˆ‘们ä¸ç›´æŽ¥ä½¿ç”¨ä»–们,而是通过一些 io åº“å‡½æ•°æ¥æ“作,他们å¯ä»¥å¯¹æ–‡ä»¶æ“作进行 buffer 等处ç†ã€‚

p127 从系统调用的级别æ¥è¯´ï¼Œlinux 把一切都当文件æ¥ï¼Œéƒ½å¯ä»¥è¿›è¡ŒåŸºæœ¬çš„ open, close, read, write, ioctl æ“作。

文件的创建时间等属于值ä¿å­˜åœ¨æ–‡ä»¶ç³»ç»Ÿä¸­æ‰€è°“的文件信æ¯èŠ‚ç‚¹ inode 中,而目录就是一个ä¿å­˜èŠ‚ç‚¹æ•°ä»¥åŠæ–‡ä»¶åçš„æ–‡ä»¶ã€‚åˆ é™¤ä¸€ä¸ªæ–‡ä»¶çš„æ—¶å€™ï¼Œå¾€å¾€åªæ˜¯ä»Ž”目录文件”中删除这个文件的相关信æ¯ï¼Œå¹¶å‡å°‘ç›®å½•ä¸­çš„èŠ‚ç‚¹æ•°ï¼›åŒæ—¶ï¼Œæ¯ä¸ªæ–‡ä»¶éƒ½æœ‰ä¸€ä¸ª link 数,一般 link 数为 1,我们用 ln 命令创建一个 link ,link æ•°å°±å˜æˆäº† 2 ,一个删除文件的æ“作会把文件的 link æ•°å‡ 1 。当一个文件的 link æ•°å˜æˆ 0 时,相关的文件信æ¯èŠ‚ç‚¹ä»¥åŠæ–‡ä»¶æ•°æ®å—(block)都会被标记为空闲(free),其他文件å¯ä»¥å†™å…¥ã€‚删除文件的æ“作并ä¸ä¼šç ´å文件本身的数æ®å†…容—一直到有其他相关的数æ®å†™å…¥ã€‚

p128 有三个é‡è¦è®¾å¤‡åœ¨ linux å’Œ unix 下都会存在。 /dev/console å’Œ /dev/tty , /dev/null 。

/dev/console 为系统控制å°(system console),系统的错误和诊断信æ¯éƒ½ä¼šå†™åˆ°è¯¥è®¾å¤‡æ–‡ä»¶ã€‚

/dev/tty 是控制终端进程(键盘和å±å¹•,或窗å£)的别å,一些系统å¯åŠ¨çš„è¿›ç¨‹æ˜¯æ²¡æœ‰æŽ§åˆ¶ç»ˆç«¯çš„ï¼Œæ‰€ä»¥ä¸èƒ½å¤Ÿæ‰“开这个文件。在有控制终端的情况下,我们å¯ä»¥é€šè¿‡å†™è¯¥è®¾å¤‡æ¥å‘用户输出写信æ¯ï¼Œåœ¨æ ‡å‡†è¾“出设备被é‡å®šå‘的时候,æ“作该设备就éžå¸¸æœ‰æ„义了。

/dev/null 是个空设备,任何写到该设备的信æ¯éƒ½ä¼šè¢«ä¸¢å¼ƒã€‚

设备被分为å—设备和字符设备(block device, character devide),这是根æ®è®¾å¤‡æ“作的最å°å•å…ƒæ¥åŒºåˆ†çš„,典型的å—è®¾å¤‡ä¸ºç¡¬ç›˜ï¼Œæ¯æ¬¡æ“作都必须是以å—(blcok) 为å•元。

p129 系统调用和设备驱动 系统调用是 UNIX/Linux(内核)直接æä¾›çš„,是æ“作系统跟用户的最低层接å£ã€‚/dev 下的设备文件都å¯ä»¥é€šè¿‡ç³»ç»Ÿè°ƒç”¨ open(打开一个文件/设备), read(从一个打开的文件/设备中读), write(往打开的文件/设备中写), close(关闭打开的文件), ioctl(å‘设备å‘出控制æ“作行为的指令) æ¥æ“作。ioctl 用æ¥å‘é€è·Ÿç¡¬ä»¶ç›¸å…³çš„æ“ä½œæŒ‡ä»¤ï¼Œä¸åŒçš„硬件支æŒçš„æŒ‡ä»¤ä¸åŒã€‚比如å‘ç£å¸¦è®¾å¤‡å‘出倒带指令。

p130 库函数 对一般的文件æ“作æ¥è¯´ï¼Œä½¿ç”¨ç³»ç»Ÿè°ƒç”¨æ•ˆçއå¯èƒ½ä¼šæ¯”较低。由于系统调用需è¦ä»Žè¿è¡Œç¨‹åº¦æœ¬èº«ä»£ç åˆ‡æ¢åˆ°å†…核代ç ï¼Œæ‰€ä»¥ä¼šä¸€å®šç¨‹åº¦ä¸Šé™ä½Žæ€§èƒ½ã€‚通常æ¥è¯´ï¼Œä¸€èˆ¬éƒ½ä¿æŒå°‘é‡çš„系统调用而尽é‡ç”¨åº“函数,比如用一次读å–大é‡çš„æ•°æ®è€Œä¸æ˜¯ä¸€ä¸ªå­—èŠ‚ï¼›ä¸€èˆ¬å­˜å‚¨è®¾å¤‡éƒ½æ˜¯æŒ‰ç…§å—æ¥è¯»å†™çš„,对一次系统调用的æ“作有严格的大å°é™åˆ¶ï¼Œå¯èƒ½é€ æˆç©ºé—´çš„æµªè´¹ã€‚比如ç£å¸¦æœºçš„一个 block å¯èƒ½æ˜¯ 10k ï¼Œæ¯æ¬¡å†™æ“作都åªèƒ½å¤Ÿæ˜¯ä»¥ 10k 为å•元,如果一次æ“ä½œåªæœ‰ 1k ,就会浪费 9k 的空间。而如果能把多次写æ“作åˆå¹¶ï¼Œå°±å¯èƒ½èƒ½å……分利用存储空间了。一般æ“作ç£ç›˜éƒ½ä½¿ç”¨æ ‡å‡†çš„ io 库,通过有效读写 buffer ,能够大大的æé«˜æ€§èƒ½ï¼Œè¿˜å¯ä»¥èŠ‚çœç£ç›˜ç©ºé—´ã€‚

Shell 编程2(Beginning Linux Programming 笔记3)

Posted in: Linux 编程 — Hick @ 2008/12/08 13:32:22 Comments (0)

原文地å€: http://www.hickwu.com/?p=260
作者: Hick
转载请注明出处

p76 列表(list) AND 列表和 OR 列表跟 C 语言里的逻辑è¿ç®—类似。AND 列表类似 “statement1 && statement2 && statement3″, OR åˆ—è¡¨å½¢å¼ “statement1 || statement2 || statement3″ ã€‚ä¸ºäº†å®žçŽ°æ›´å¤æ‚的语å¥åˆ—表,有时候å¯ä»¥ä½¿ç”¨ {} 包å«çš„语å¥å—(还没有实践):

get_confirm && {
  grep -v “$cdcatnum†$tracks_file > $temp_file
  cat $temp_file > $tracks_file
  echo
  add_record_tracks
}

p79 bash å‡½æ•°åŒæ ·éœ€è¦å…ˆå®šä¹‰åŽä½¿ç”¨ï¼Œä½†æ˜¯è°ƒç”¨æ–¹å¼è·Ÿ C é‡Œç¨æœ‰ä¸åŒã€‚

foo() {
  echo “Function foo is executingâ€
}
echo "script starting"
foo
echo "script ended"

p80 å‰é¢ä»‹ç»çš„è„šæœ¬å‚æ•°å˜é‡ï¼š “$*, $@, $#, $1, $2″ 等在函数体内,都æˆäº†å‡½æ•°çš„傿•°çš„载体。函数以外其值ä»ç„¶ä¸ºè„šæœ¬å‚æ•°çš„载体。有些 shell å¯èƒ½ä¸æ˜¯è¿™ä¹ˆå¤„ç†çš„ï¼Œæ‰€ä»¥ä¸€èˆ¬è„šæœ¬ä¸­çš„å‚æ•°ä½¿ç”¨ä¸€èˆ¬ä¸å»ºè®®ä¾èµ–这几个å˜é‡ã€‚

关于函数的返回值,数字一般通过 return 返回,而字符串通常通过把字符串存储到一个å˜é‡çš„æ–¹å¼å®žçް(函数内å¯ä»¥ç›´æŽ¥æ“作全局å˜é‡)。也å¯ä»¥åœ¨å‡½æ•°ä¸­ echo 输出字符串,通过这样的返回获得函数输出的字符串: returnStr = “$(func)” 。

函数内部å¯ä»¥å®šä¹‰å±€éƒ¨å˜é‡ï¼Œå‡½æ•°æ‰§è¡Œå®Œæ¯•以åŽï¼ŒåŒå全局å˜é‡å¹¶ä¸ä¼šå—å½±å“,如下:

sample_text="global variable"
foo() {
  local sample_text="local variable"
  echo "Function foo is executing"
  echo $sample_text
}
echo "script starting"
echo $sample_text
foo
echo "script ended"
echo $sample_text

p81 一个函数的简å•应用,值得注æ„çš„æ˜¯å‡½æ•°å‚æ•°çš„传递形å¼ä»¥åŠè¿”回值的判断:

yes_or_no() {
  echo "Is your name $* ?" # p81.2
  while true
  do
    echo -n "Enter yes or no: "
    read x
    case "$x" in
      y | yes ) return 0;;
      n | no )  return 1;;
      * )       echo "Answer yes or no"
    esac
  done
}

echo "Original parameters are $*"

if yes_or_no "$1"  # p81.1
then
  echo "Hi $1, nice name"
else
  echo "Never mind"
fi

调用的时候执行 ./hick.sh hick youname 以åŽï¼Œè¾“入选项å³å¯ã€‚p81.1 å¤„æŠŠè„šæœ¬çš„ç¬¬ä¸€ä¸ªå‚æ•°æ¯”如 hick 传递给函数,函数中的 p81.2 èŽ·å¾—å‡½æ•°çš„æ‰€æœ‰å‚æ•°ä¹Ÿå°±æ˜¯ hick ,函数一直执行直到用户选择 yes/no ,选择正确的值以åŽè¿”回 0 或者 1 ,这时候 p81.1 å°±å¯ä»¥æ‰§è¡Œäº†ã€‚

p82 shell 中å¯ä»¥ä½¿ç”¨çš„命令通常分为内部命令和外部命令,内部命令是由 shell 本身实现的比如 break。有些命令内部外部都有实现,一般我们ä¸éœ€è¦å…³æ³¨ã€‚è·Ÿ C 语言类似, break 用æ¥è·³å‡ºå¾ªçŽ¯ç­‰ï¼Œé»˜è®¤æƒ…å†µä¸‹åªè·³å‡ºä¸€ä¸ªå±‚æ¬¡ï¼ŒåŒæ ·ä¹Ÿæœ‰ continue 命令。

p83 命令 : 等价与 true ,ä¸è¿‡æ˜¯ shell 内置命令,所以速度比较快。

p84 命令 . 用在命令或者脚本å‰é¢ã€‚è¡¨ç¤ºåœ¨å½“å‰ shell 环境下执行—ä¸å¸¦ç‚¹æ—¶ï¼Œä¼šæ–°å»ºä¸€ä¸ª shell 环境(æ–°çš„ shell 进程,包括环境å˜é‡ç­‰)去执行。常è§çš„一个问题: å½“å‰ shell 设置的一个环境å˜é‡åœ¨è¿è¡Œçš„脚本中无法使用,出æ¥ç”¨ . 命令的方å¼ï¼Œä¸€èˆ¬éƒ½æ˜¯ç”¨ export 命令在脚本中对å˜é‡æˆ–者环境å˜é‡è¿›è¡Œè®¾ç½®ã€‚(p87)

p86 eval 命令å¯ä»¥æŠŠä¸€ä¸ªå­—符串当 shell å‘½ä»¤æ¥æ‰§è¡Œï¼Œä¸ä¼šæ–°å»ºä¸€ä¸ª shell 环境。exec 一般会执行一个外部命令,替æ¢å½“å‰ shell 进程。

p87 exit è·Ÿ c 语言类似,用æ¥è¾“出一个编ç ï¼Œä¸€èˆ¬è¾“出 0 表示执行æˆåŠŸï¼Œ1-125 的值表示表示错误ç ï¼Œæ„味ç€è„šæœ¬æ‰§è¡Œå‡ºäº†é—®é¢˜ã€‚

p88 因为 shell 处ç†å­—符串的特殊性,这样的语å¥å¹¶ä¸ä¼šæ‰§è¡Œç®—术è¿ç®—,而是进行字符串è¿ç®—: $num2=$num+1 。实现这样的功能,通常通过 expr æ¥å®Œæˆï¼Œæ³¨æ„由于 + 等是 expr çš„å‚æ•°ï¼Œæ‰€ä»¥å·¦å³å¿…须有空格。expr çš„ä½œç”¨å°±æ˜¯ç”¨æ¥æ‰§è¡Œè¡¨è¾¾å¼ï¼š $num = `expr $num + 1` ,这里 “ 表示执行它所包å«çš„命令,并返回命令的结果。用 $() æ˜¯åŒæ ·çš„æ•ˆæžœï¼š $(expr $num + 1) 。 expr 支æŒå¤§å¸¸è§çš„算术è¿ç®—(p89)。

p89 bash 里也支æŒç±»ä¼¼ C çš„ printf 语法。

p91 set å¯ä»¥ç”¨æ¥æ”¹å˜è„šæœ¬çš„å‚æ•°ï¼Œæ¯”如通过 set -x å¯ä»¥ç”¨æ¥ä»¥è°ƒè¯•默认跑脚本。 set $(date) å¯ä»¥æŠŠ date 命令的返回结果当åšè„šæœ¬çš„å‚æ•°ï¼Œè¿™æ—¶å€™å¯ä»¥é€šè¿‡ $* 等获得å„ä¸ªå‚æ•°ã€‚é’ˆå¯¹å‚æ•°çš„还有 shift 命令,用æ¥ç§»èµ°ç¬¬ä¸€ä¸ªå‚æ•° $1 ,原æ¥çš„ç¬¬äºŒä¸ªå‚æ•°å˜æˆçŽ°åœ¨çš„ç¬¬ä¸€ä¸ªå‚æ•°ï¼ŒåŽé¢çš„便­¤ç±»æŽ¨ã€‚

p92 trap 命令用æ¥å®šä¹‰è„šæœ¬å¯¹å¤–éƒ¨ä¿¡å·çš„å¤„ç†æ–¹å¼ï¼Œæ¯”如 C-c 触å‘çš„ interrupt 中断信å·ã€‚这样就å¯ä»¥ä½¿å¾—脚本在执行过程中ä¸å“应 C-c 而终止。定义了å„ç§å¯å¤„ç†ä¿¡å·çš„ç¼–ç ã€‚

p94 unset 命令用æ¥åˆ é™¤å·²ç»å®šä¹‰çš„å˜é‡æˆ–者函数。当然,对一些åªè¯»çŽ¯å¢ƒå˜é‡æ¯”如 $IFS 等是ä¸å¯ä»¥æ“作的。

p95 虽然ä¸å±žäºŽ shell çš„å†…å®¹ï¼Œä½†æ˜¯ä¸ºäº†æ–¹ä¾¿ä»‹ç»æ­£åˆ™è¡¨è¾¾å¼ï¼Œå…ˆçœ‹ä¸‹ find å’Œ grep 两个命令。 find / -mount -name test -print 中的 -print 一般是å¯é€‰çš„,表示输出文件å, -mount è¡¨ç¤ºä¸æœç´¢ mount 目录。 find 的标准用法是 find [path] [options] [tests] [actions] ,其中 tests 为需è¦å¯»æ‰¾çš„æ–‡ä»¶çš„匹é…规则。find 还有 -maxdepths 定义æœç´¢çš„目录层次,还å¯ä»¥æŒ‰ç…§æ–‡ä»¶çš„è®¿é—®æ—¶é—´ã€æ‰€æœ‰è€…等相关æ¡ä»¶è¿›è¡Œå¯¹æ¯”。-type C ç”¨æ¥æŒ‡å®šæœç´¢çš„æ–‡ä»¶ç±»åž‹ï¼Œå¸¸è§çš„ C 为 f 表示一般文件, d 为目录。

p97 å¯ä»¥å¯¹æ¯”一个文件,æœç´¢æ¯”文件 while2 修改时间更新的: find . -newer while2 -type f -print 。一般æ¥è¯´ï¼Œæˆ‘们还会针对æœç´¢ç»“果采å–一些æ“作。常用的 -exec command å’Œ -ok commandã€-ls 等。å‰ä¸¤ä¸ªé€‰é¡¹æŠŠ find 返回的结果的æ¯ä¸€åˆ—当 command å‘½ä»¤çš„å‚æ•°ï¼Œå…·ä½“用 {} æ¥å ä½ï¼š find . -newer while2 -type f -exec ls -l {} \; 最åŽçš„ \ 表示 -exec çš„å‚æ•°çš„结æŸã€‚

p98 grep çš„è¯­æ³•æ ¼å¼ grep [options] PATTERN [FILES] ,当没有指定任何文件时,grep 针对标准输入信æ¯åšåŒ¹é…。常用的 -r 傿•°è¡¨ç¤ºé€’å½’æœç´¢ç›®å½•。

p99 正则表达å¼ã€‚常用符å·çš„æè¿°ï¼š ^ 开头, $ 结尾, . ä»»æ„一个字符, ? åŒ¹é… 0 个或 1 个, * åŒ¹é… 0 个或者多个, + åŒ¹é… 1 个或者多个。比如寻找文件中以 e 结尾的行: grep e$ file.txt ;寻找文件中 a åŽé¢æŽ¥ä¸€ä¸ªç©ºæ ¼/制表符的行: grep a[[:blank:]] file.txt 。

p103 å‰é¢ä»‹ç»é€šè¿‡ expr å¯ä»¥å®žçŽ°ç®—æœ¯è¿ç®—,但是这样的æ“作是外部命令需è¦å¯åŠ¨ä¸€ä¸ªæ–°çš„ shell æ¥æ‰§è¡Œï¼Œè€Œä»¥ bash 内部实现的方å¼ï¼Œå¯ä»¥ç”¨ $expresion æ¥å®žçŽ°ï¼Œæ¯”å¦‚ x=$(($x+1)) ,注æ„语法上空格的ä¸åŒã€‚

需è¦åœ¨å˜é‡ var åŽè¿½åŠ å­—ç¬¦ä¸² _temp çš„è¯ï¼Œä¸èƒ½å¤Ÿè¿™æ · $var_temp ,这样 shell 会当作å˜é‡ $var_temp æ¥è§£é‡Šã€‚这时候我们需è¦ç”¨å˜é‡çš„原生表现方å¼ï¼Œä¹Ÿå°±æ˜¯ ${var}_temp è¿™ç§æ–¹å¼ã€‚䏋颿˜¯å‡ ç§å˜é‡çš„å½¢å¼ï¼š ${param:-default} 如果 param 为 null å€¼ï¼Œåˆ™è®¾ç½®æˆ default ï¼› ${#param} 返回 param 的长度。下é¢è¿™æ®µæ“作实现截å–字符:

foo=/X11/usr/X11/bin/X11/startx
echo ${foo#*X11}        # /usr/X11/bin/X11/startx
echo ${foo##*X11}       # /startx
bar=/usr/local/etc/local/networks
echo ${bar%local*}      # /usr/local/etc/
echo ${bar%%local*}     # /usr/

p106 HERE DOC å¯ä»¥æ”¯æŒå¤šè¡Œä¹¦å†™å­—符串,跟 PHP 等中的ä¸ä¸€æ ·çš„æ˜¯ï¼Œshell 里的 HERE DOC 用两个 < å³å¯ã€‚

p107 通过 sh [傿•°] [脚步] å¯ä»¥å¯¹è„šæœ¬è¿›è¡Œä¸€äº›ç®€å•的调试,å‰é¢ä»‹ç»è¿‡ set ,所以我们å¯ä»¥åœ¨è„šæœ¬å†…éƒ¨ç›´æŽ¥é€šè¿‡ set æ¥è®¾ç½® sh çš„å‚æ•°ï¼Œåˆ—表如下:

sh -n <script> 等价于 set -o noexec 或 set -n , æ£€æŸ¥è¯­æ³•é”™è¯¯ï¼Œä¸æ‰§è¡Œè„šæœ¬

sh -v <script> 等价于 set -o verbose 或 set -v ,执行命令先输出命令

sh -x <script> 等价于 set -o xtrace 或 set -x ,执行命令以åŽè¾“出命令

sh -u <script> 等价于 set -o nounset 或 set -u ,当使用了未定义å˜é‡æ—¶è¾“出错误信æ¯

在脚本中通过 set -o 打开一个选项以åŽï¼Œè¿˜å¯ä»¥é€šè¿‡ set +o 的方å¼å…³é—­ç›¸åº”选项。

p108 命令行图形界é¢ï¼š diglog å®žç”¨å·¥å…·ï¼Œè¯•äº†ä¸‹è¿™ä¸ªå®žç”¨å·¥å…·ä¸æ€Žä¹ˆå¥½ç”¨ï¼Œ RHEL å’Œ slackware 都支æŒä¸å¥½ã€‚

Next Page »