Problem 43. 常用Shell命令集。
Ans:
1. cut
将输入行的特定字段裁剪出来,默认情况下cut将tab视为字段分隔符。cut不影响输入文件。
-b list 显示出位于list所指位置的字节。
-c list 显示出位于list所指位置的字符。
-d delim 定义字段分隔符为delim字符。
-f list 显示出list所列出的字段。
范例:
$ cut –d: -f1 /etc/passwd
$cut –c 1 /etc/passwd
2. head
显示出文件开头的前几行。
-c n 显示出前n个字节的内容。若n后面附加了k或m,则计数单位会相应变成千字节(KB)或兆字节(MB)。
-n m 显示出头m行的内容,默认值为10。
3. join
依据所指定的字段将来自file1与file2的两个表格合并成一个表格
-j1 nfield
索引字段为file1的第nfield个字段
-j2 nfield
索引字段为file2的第nfield个字段
-j nfield
将file1与file2共同的field视为索引字段。
$ join –j 1 file1 file2
4. od
以八进制数据格式显示文件内容
-t type
a 字符名称
c ASCII
o 八进制
x 十六进制
$ od –t a file1
$od –t c file1
$od –t x1 file1(每个数值代表一个字节)
$od –t x2 file1(每个数值代表两个字节)
5. sort
读取输入内容,以字母顺序(或其他顺序)输出它们
-f 不区分大小字母差异。
-n 以数值顺序排序
-r 以相反的顺序排序
-k pos1, [, pos2] 以位于pos1(到pos2)的键值为排序依据
-t sep 改以sep为区别键值的分隔字符(默认值为空格符)
$ ps –aux | sort –k 6 -n
6. tac
颠倒输入行的顺序,刚好与cat的效果相反。
7. tail
显示出一个或多个文件中的最后几行。
-c n 显示出文件最后n个字节的内容。若n后面附加了k或m,则计数单位会相应变成千字节(KB)或兆字节(MB)。
-n m 显示出最后m行的内容,默认值为10。
-f 显示出文件尾端内容后不关闭输入文件,并且在输入文件的末端出现新内容时实时将它们显示出来。常用此项来持续观察日志文件的内容变化情况。
8. tr string1 string2
将一个字符串里的字符转译为另一个字符串里相应的字符
-c 以相反意义解释string1
-d 丢弃出现于string1中的任何字符
-s 若输入数据中连续出现string1所含的任一字符,则将连续字符挤压到只剩一个。
$ cat file1 | tr a-z A-Z
$ cat file1 | tr –s a 消除file1中连续的字符a
$ cat file1 | tr –d abc 删除file1中所有的字符a, b, c
9. uniq
消除连续相同的文本行。通常与sort搭配使用。
-d 只显示出有重复的行
-u 只显示出不重复的文本行
-c 计算重复次数
$ sort file | uniq
$sort file | uniq -d
10. wc
计算文件内容中的字符数、单词数和行数。
-c 只显示出字符数
-l 只显示行数
-w 只显示出单词数
$ ls | wc -l
11. xargs [选项] [其他命令] [初始参数]
将来自stdin的数据逐一作为other_cmd的自变量,逐次执行新的命令直至耗尽stdin为止。如果要执行的新命令有固定的选项或参数,则可以在初始参数列表予以指定。从stdin读入的参数会接在初始参数列表之后。
主要用于解决命令行过长的问题或需要从其他命令的执行结果中中得到所欲执行命令的自变量。
-n maxargs 限制每次传给其他命令的额外自变量的数量。
-p 交互模式。执行新构成的其他命令之前会提示用户进行确认。
$ ls | xargs rm
$ find / -type f | xargs –n 1 grep linux
12 find paths expression [action]
常用搜索条件:
-name pattern
-path pattern
-lname pattern
找出名称(-name)、路径名称(-path)或符号链接的目标(-lname)匹配pattern模式的文件。pattern可包含shell的文件名通配符(*,? 和[]),路径是相对于搜索起点的。
-regex regexp
路径(相对于搜索起点),必须符合regexp正则表达式的描述
-type f|d|l|b|c|p|s
只搜索普通文件(f)、目录(d)、符号链接(l)、块设备(b)、字符设备(c)、具名管道设备(p)或socket(s)。
-maxdepth N
-mindepth N
限制搜索的深度(相对于搜索起点的子目录深度),至少(-mindepth)或最深(-maxdepth)为N层
-size N[bckw]
找出大小为N单位的文件。b, c, k, w分别代表块、单字节字符、千字节()、双字节字组。+N表示大于N,-N表示小于N。
-empty
找出长度为0的普通文件或目录。
-user username
-group gpname
拥有者为username用户或gpname组
-perm mode
找出访问模式等于mode的文件或目录。使用-mode表示指定位都必须全部设置,而+mode表示任何指定位之一被设置就算符合条件。
常见的处理动作
显示出文件的相对路径(相对于搜索起点)
-exec cmd /;
执行指定的shell命令(cmd)。若cmd含有任何shell特殊字符,则它们之前都必须加上/字符,以免shell立即执行它们。在cmd里,可以用”{}”符号(包括双引号在内)来表示find所找出的文件。
$ find src/ -name “*.c”
$ find src/ -name “*.c” –exec chmod g+w {} /;
从根目录开始,找出任何设置了SUID属性文件并产生一份文件列表
$ find / -type f –perm -4000 –print | tee /tmp/suid_filelist
找出工作目录下所有的.zip压缩文件并解压缩它们:
$ find . –name ‘*.zip’ –exec unzip “{}” /;
PS:当查找一个文件名已知的文件,用locate更好。
13 grep
-c
只显示匹配模式行的数目,而非匹配模式行本身。
-h
同时搜索多个文件时只显示匹配模式和本身,而不加注所属文件。
-i
忽略大小写字母的差异。也就是说,模式abc的匹配模式行可以是abc, aBc, Abc, ABC。
-n
加注匹配模式行于原文件中的行号。若有多个输入文件时,则文件名与行号都会被显示出来。
-o
只显示匹配模式的字符串,而不是含有该字符串的整个行。
-v
显示出不匹配模式的行
-E
以扩展语法来解释regexp, 而不是含有该字符串的整个行。
例子:
1. 查找含有“linux”或“Linux”字样的行
$: grep –i linux file1
$: grep [Ll]inux file1
$: grep “/<[Ll]inux” file1
2. 取出收信人为(to=)@oreilly.com.tw的所有通信记录:
$: grep –o “to=.*@oreilly/.com/.tw” /tmp/aug22.log /tmp/aug22.oreilly
14 sed
流过滤工具
-e cmd
代表其后的自变量是一道命令。指定多重命令时,每个命令之前都必须以本选项指出。
-f file
代表其后的自变量是一个脚本。
-g
替换操作的影响范围为“全局”。
编辑命令:
d
删除整行文本。
s
替换。这是常用的编辑命令,其语法是:
s/pattern/replacement/[flags]
flags的值可能为:
g 全局替换。全文中任何与pattern相匹配的每个文段都会被替换成replacement,而不是只有第一个相匹配者。
n 替换第n个与pattern相匹配的文段。默认值为1。
p 显示出被成功替换的行。引标记通常会与-n命令行选项并用。
w file 将完成替换的文本行输出到file文件。
y 执行类似于tr命令的转换程序。
例子:
1. $: sed ‘3, 5d’ file1 删除文件的第三行到第五行
2. $: sed ‘/^#/d’ file1 删除文件中所有以井字号为首的行
3. $: sed y/abc/xyz/ file1 把字母a,b,c换成x,y,z
4. $: sed ‘s/^$/@/’ file1 把空行换成@符号
5. $: sed ‘s/”/’/g’file1
15. pushd, popd, dirs
这几个命令可以使得工作目录书签化,就是可以按顺序向前或向后移动工作目录.
压栈的动作可以保存工作目录列表.选项可以允许对目录栈作不同的操作.
pushd dir-name 把路径dir-name 压入目录栈,同时修改当前目录到dir-name.
popd 将目录栈中最上边的目录弹出,同时修改当前目录到弹出来的那个目录.
dirs 列出所有目录栈的内容(与$DIRSTACK 便两相比较).一个成功的pushd 或者popd 将会
自动的调用 dirs 命令.
下面的命令顺序会说明该命令如何工作:
[PWD david]$ dirs
~
[PWD david]$ pushd /etc/
/etc ~
[PWD etc]$ pushd /var/
/var /etc ~
[PWD var]$ pushd /mnt/
/mnt /var /etc ~
[PWD mnt]$ pushd /home/
/home /mnt /var /etc ~
[PWD home]$ dirs
/home /mnt /var /etc ~
[PWD home]$ popd
/mnt /var /etc ~
[PWD mnt]$ popd
/var /etc ~
[PWD var]$ popd
/etc ~
[PWD etc]$ popd
比较常用的操作是将您的工作目录定义到目录列表中:
pushd $PWD
Problem 44 关于函数指针的使用?
Ans:
Ex1: 形式一
#include <unistd.h>
#include <stdio.h>
int max(int a, int b)
{
return a > b ? a:b;
}
typedef int (p)(int, int);
int test(p f, int a, int b)
{
p* func = f;
return func(a, b);
}
int main()
{
int a=10;
int b=9;
int c;
c = test(max, a, b);
printf("c=%d/n", c);
return 0;
}
Ex2 形式二
#include <unistd.h>
#include <stdio.h>
int max(int a, int b)
{
return a > b ? a:b;
}
typedef int (*p)(int, int);
int test(p f, int a, int b)
{
p func = f;
return func(a, b);
}
int main()
{
int a=10;
int b=9;
int c;
c = test(max, a, b);
printf("c=%d/n", c);
return 0;
}
Problem 45. Bash Shell简明教程?
Ans:
1. 常用shell变量
$#:存储外壳程序中命令行参数的个数。
$?:存储上一个执行命令的返回值。
$0:存储外壳程序的程序名。
$*:是所有位置参数的列表(不包括$0),其形式是单个字符串,串中每个参数由内部域分隔符$IFS分隔。
$@:存储所有命令行的输入参数,是所有位置参数被分别表示为双引号中的N个字符串,分别表示为($1, $2, …, $n)。
$$:存储外壳程序的PID。
$!:存储上一个后台执行命令的PID。
shell数组:
定义:
declare -a SATA_DEVS
SATA_DEVS=( "sda 8 0 6 644"
"sdb 8 16 6 644"
"sdc 8 32 6 644"
"sdd 8 48 6 644"
"sde 8 64 6 644"
"sdf 8 80 6 644"
)
访问数组中的元素:
NUM_ELEMS=${#SATA_DEVS[@]}
for (( i=0; i<$NUM_ELEMS; i++)); do
this_entry=${SATA_DEVS[${i}]}
echo $this_entry
done
2. test命令
1) 整数运算符
int1 –eq int2
int1 -ge int2
int1 -gt int2
int1 -le int2
int1 -lt int2
int1 -ne int2
2) 字符串运算符
str1 = str2
str1 != str2
str 如果str不为空,则返回真
-n str 如果str长度大于零,则返回真
-z str 如果str长度等于零,则返回真
3) 文件运算符
-d filename 是否为目录
-e filename 文件是否存在
-f filename 是否为普通文件
-r filename 是否只读
-s filename 长度是否大于零
-w filename 是否可写
-x filename 是否可执行
-L filename 是否为软链接文件
file1 –ot file2 若file1旧于file2,则条件成立
4)逻辑运算符
!expr 非
expr1 –o expr2 或
expr1 –a expr2 与
3. 条件表达式
1) if表达式
if [ expression ]
then
commands
elif [ expression ]
then
commands
else
commands
fi
例子:
if [ -f .profile ]
then
echo “There is a .profile int the current directory.”
else
echo “Cound not find the .profile file.”
fi
2) case 表达式
case string1 in
str1)
commands
;;
str2)
commands
;;
*)
commands
esac
例子:
case $1 in
-i)
count=`grep ^i $2 | wc –l`
echo “the number of lines in $2 that start with an i is $count”
;;
-e)
count=`grep ^e $2 | wc –l`
echo “the number of lines in $2 that start with an e is $count”
;;
*)
echo “That option is not recogonized”
;;
esac
3) 循环语句
1. for 语句
第一种形式:
for var int list
do
commands
done
第二种形式:
for var (in “$@”)
do
statements
done
例子:
for file
do
tr a-z A-Z <$file >$file.caps
done
2. while语句
while expression
do
statements
done
例子:
count=1
while [ -n “$*” ]
do
echo “This is parameter number $count $1”
shift
count=`expr $count + 1`
done
3. until语句
until expression
do
commands
done
例子:
count=1;
until [ -z “$*” ]
do
echo “This is parameter number $count $1”
shift
count=`expr $count + 1`
done
4) shift 命令
shift命令用来将存储在位置参数中的当前值左移一个位置
例子:
while [ “$1” ]
do
if [ “$1” = “-i” ]
then
infile=”$2”
shift 2
elif [ “$1” = “-e” ]
then
outfile=”$2”
shift 2
else
echo “Program $0 does not recognize option $1”
fi
done
tr a-z A-Z <$infile >$outfile
4. 函数
形式:
fname()
{
command
… …
command
}
调用函数形式:
fname [param1 param2 param3 …]