Linux基础学习(1)——浅释程序库与脚本
1.程序库
1.1 什么是库文件
库文件是已经编译完毕、可被其他程序调用的函数集合。标准系统库文件的常见路径为/lib/usr/lib等。库文件的命名方式为lib*,如C语言共享库libc.so,数学静态库libm.a。
1.2 静态库与共享库
.a代表静态库(即归档文件,achieve)。当程序p使用静态库时,需包含相应的声明库函数的头文件,编译器和链接器将程序p与函数库结合为一个可执行文件,即在程序p中存在静态库的一份副本,可见若多个程序多次调用,会因为大量的副本而产生极大的内存浪费。
.so代表共享库。当程序p使用共享库时,是在编译完成后装载到内存中执行时,引用运行时可访问的共享代码。
项目 | UNIX | Windows |
---|---|---|
目标模块 | .o | .obj |
静态库 | .a | .lib |
共享库 | .so | .dll |
可执行程序 | 无扩展 | .exe |
1.3与库相关的简单命令
1.3.1 gcc命令
#program 为样例文件名
$ gcc -c program.c
# gcc -c [C程序文件名] 仅编译,不连接
$ gcc -o program program.o
# gcc -o [可执行程序文件名] [目标模块文件名] 连接生成可执行程序
$ gcc -o program program.o libc.a
# gcc -o [可执行程序文件名] [目标模块文件名] [用到的静态库] 使用静态库连接生成可执行程序
$ gcc -o program program.o -L. -lc
# gcc -o [可执行程序文件名] [目标模块文件名] -L. [用到的静态库] 寻找并使用静态库连接生成可执行程序,-lc代表libc.a
1.3.2 ar命令(&ranlib命令)
$ ar crv libfoo.a program1.o program2.o
# ar crv [静态库名] [(多个)目标文件名] 创建静态库文件集合
$ ranlib libfoo.a
# ranlib [静态库名] 函数库生成内容表
1.3.3 ldd命令
$ ldd program
#ldd [可执行文件名] 查看程序需要的共享库
2.脚本shell
2.1 一些简单命令
2.1.1 重定向
$ cd ~
$ touch ex.txt #新建实验文件
$ ls > ex.txt #将ls ~ 的结果写入ex.txt (覆盖原有内容)
$ ls >> ex.txt #将ls ~ 的结果插入到ex.txt (接在原有内容之后)
2.1.2 管道操作|
管道操作可将进程连接起来
$ ps | uniq | grep -v sh | more
#ps: 列举所有进程
#uniq:去除同名
#grep -v 删除关键字相关(删除名为sh的进程)
#more:分页列举输出
2.1.3 通配符 * ?
$ cd ~
$ mkdir -p ex/ex10 ex/ex20 ey/ey10 ey/ey20
#mkdir -p 创建不存在的父目录
$ ls e?
#通配符?用于匹配单个字节,相当于对ex和ey进行ls操作
$ ls ex/*1
#通配符*用于匹配d多个字节,相当于对ex10进行ls操作
$ ls ex/ex{1,2}0
#使用集合,相当于对ex10和ex20进行ls操作
2.2 一个简单的脚本文件
新建脚本文件
$ cd ~/ex/
$ touch first.sh
$ vim first.sh #用别的编辑器也无所谓
2.2.1 文件开头
#!/bin/sh
#!为特殊注释符,所带参数为用来执行该脚本文件的程序(这里的/bin/sh为默认shell程序)
2.2.2 文件内容(样例:文件查找)
for file in * #遍历所有文件
do
if grep -q ex $file #查找名称中含有‘ex’字样的文件夹
then
echo $file #显示
fi
done
2.2.3 文件结束
exit 0
exit确保脚本返回一个有意义的退出码。如果需要在其他程序中调用该脚本程序,则需要检查退出码来检查程序是否成功执行,一般设置成功为0。
2.3 脚本文件运行
两种方法:
1.直接运行
$ /bin/sh first.sh
2.赋予可执行文件权限
$ chmod +x first.sh
./first.sh
输出
grep: ex10: Is a directory
grep: ex201: Is a directory
first.sh
2.4 shell语法
2.4.1 shell变量 & 函数
2.4.1.1 自定义变量
shell中的所有变量均为字符串
$ sa=Hello #给变量赋值 ,= 前后不要加空格,因为空格被视为命令/参数分隔符
$ echo $sa #运算符$可以访问变量的值,echo命令可输出到终端
Hello
$ sa="Hello world" #变量中含空格必须加引号
$ echo $sa
Hello world
$ sa=1+1 #给变量赋值数值/表达式仍用字符存储
$ echo $sa
1+1
$ read sa #接受用户从键盘键入变量值
1+1
$ echo $sa
1+1
2.4.1.2 引号与转义
对于如下脚本文件
#!/bin/sh
value="Hello world"
echo 1 $value #$转义为取值
echo 2 "$value" #双引号仅解释$ \ ` 三个字符,其余均按照字符本身处理
echo 3 '$value' #单引号所有字符按照字符本身处理
echo 4 \$value #转义符号\将紧随其后的字符按字符本身处理
exit 0
输出
1 Hello world
2 Hello world
3 $value
4 $value
2.4.1.3 环境变量&参数变量
环境变量 | 说明 |
---|---|
$HOME | 用户家目录 |
$PATH | 搜索的目录列表 |
$PS1 | 命令提示符:通常为$ |
$PS2 | 二级提示符:用于提示后续输入,通常为> |
$IFS | 输入域分隔符 |
$0 | shell脚本名 |
$# | 传递给shell参数个数 |
$$ | shell脚本进程号 |
#!/bin/sh
#参数变量举例
set var1 var2 var3 #变量赋值
echo num:$#__$1::$2::$3 # $#:变量个数 $1:第一个变量
echo $*
echo $@
#$* $@ 列举变量
IFS='' #IFS:列举变量中的分隔符
echo $*
echo $@
IFS=' '
echo $*
echo $@
exit 0
输出:
num:3__var1::var2::var3
var1 var2 var3
var1 var2 var3
var1var2var3
var1var2var3
var1 var2 var3
var1 var2 var3
2.4.1.4 函数
#!/bin/sh
s="global" #全局变量
#函数定义
foo(){
local s="local" #局部变量,生存期只在函数体内
echo 0 $s
return 0 #返回0表示正常结束
}
echo 1 $s
#函数调用&检查返回值
if foo #此处函数返回0会执行then,而非返回1 !!!!
then
echo finish
fi
echo 2 $s
exit 0
输出:
1 global
0 local
finish
2 global
2.4.2 条件语句
条件语句作为控制语句的条件出现(可理解为C语言if、while等括号里返回布尔值的表达式),一般用两种表达
text ***
[ *** ] #注意[ ] 左右均有空格
常见的 *** 的内容
字符串比较(注意字符串与运算符之间的空格) | 返回"true"的结果 |
---|---|
string1 = string2 | 两字符串相等 |
string1 != string2 | 两字符串不等 |
-n string | 字符串非空 |
-z string | 空串 |
算术比较 | 返回"true"的结果 |
---|---|
a -eq b | a == b |
a -ne b | a != b |
a -gt b | a > b |
a -ge b | a >= b |
a -lt b | a < b |
a -le b | a <= b |
文件条件 | 返回"true"的结果 |
---|---|
-d file | 文件是一个目录 |
-f file | 文件是一个文件 |
-r file | 可读 |
-s file | 大小不为0 |
-w file | 可写 |
-x file | 可执行 |
2.4.3 控制结构
2.4.3.1 if语句 & while/until语句 & case语句
(condition代表状态,state代表操作,varx代表变量var的几个值)
if condition1
then
state1
elif condition2
state2
else
state3
fi
while condition
do #condition==1则do
state
done
until condition
do #condition==0则do
state
done
case "$var" in
var1 ) state1;;
var2 ) state2;;
var3 ) state3;;
esac
case "$var" in
var1 | var4 ) state1;;
var2 | var5 ) state2;;
var3 | var6 ) state3;;
esac
2.4.3.2 for语句
#!/bin/sh
for a in 1 2 3
do
echo $a
done
exit 0
输出
1
2
3
2.4.3.3 break&continue 与C语言类似
2.4.4 常用命令
2.4.4.1 冒号(:)
空命令,代替true
2.4.4.2 点(.)
在当前脚本中执行命令
2.4.4.3 echo
输出到终端, echo -n
可用于去除换行符
2.4.4.4 eval
eval用于求值
foo = 10
x = foo
y = '$'$x
echo $y #输出:$foo
foo = 10
x = foo
eval y = '$'$x
echo $y #输出:10
2.4.4.5 return n & exit n
return:函数返回
exit:整个脚本程序返回
exit退出码 | 意义 |
---|---|
0 | 正常退出 |
1 - 125 | 脚本可以使用的错误代码 |
126 | 文件不可执行 |
127 | 命令未找到 |
>= 128 | 出现一个信号 |
2.4.4.6 export
second.sh
#!/bin/sh
echo "$a"
echo "$b"
first.sh
a=1
export b=2 #导出b
second #调用second.sh脚本
执行first.h 只导出了b,因此脚本second只能使用b
2
2.4.4.7 set & shift & unset
set用于设置变量
shift丢弃$1,将$2起所有变量左移1
unset把变量从环境中删除
set a b c #$1=a, $2=b, $3=c
shift #$1=b, $2=c
unset c #把c从环境中删除
2.4.4.8 trap
trap command signal #对signal执行command
trap signal #对signal忽略
trap - signal #对signal执行默认操作
常见signal
signal | 说明 |
---|---|
HUP(1) | 挂起(掉线/退出终端) |
INT(2) | 中断进程 一般为用户按下Ctrl+C |
QUIT (3) | 退出终端 一般为用户按下Ctrl+\ |
ABRT(6) | 中止(严重错误) |
ALRM(14) | 超时报警 |
TERM(15) | 终止(系统关机) |
2.4.4.9 find
find [路径] [选项] [测试] [动作]
常用选项
选项 | 意义 |
---|---|
-depth | 深度优先:先搜索目录内,再查看目录本身 |
-follow | 跟随符号链接 |
-maxdepths N | 最多搜索N层 |
-mount / -xdev | 只搜索挂载点 |
常用测试
测试 | 意义 |
---|---|
-atime N | 文件在N天之前被最后访问过 |
-mtime N | 文件在N天之前被最后修改过 |
-name p | 文件名匹配p |
-newer o | 文件比文件o更新 |
-type c | 文件类型为c |
-user u | 文件拥有者的用户名为u |
! -not | 测试取反 |
-a -and | 测试与运算 |
-o -or | 测试或运算 |
注: 可用\ ( \ )改变优先级,不能直接使用括号()
常用动作
动作 | 意义 |
---|---|
打印文件名 | |
-exec c | 执行命令c,该动作必须用\ ;终止 |
-ok c | 执行命令c,执行前针对每个被处理的文件需要用户确认,该动作必须用\ ;终止 |
2.4.4.10 正则表达式 & grep命令:General(通用) Regular(正则) Expression(表达式) Parser(解析器)
正则表达式中常用特殊字符
字符 | 含义 |
---|---|
^ | 行首 |
$ | 行尾 |
. | 任意单个字符 |
[ ] | 字符匹配范围 |
^[ ] | 字符不匹配范围 |
若需要将以上字符作普通字符使用,则前加 \ 转义
grep [选项] 待匹配字符串 [文件]
常用选项 | 意义 |
---|---|
-c | 输出匹配行的数目 |
-v | 输出不匹配行的数目 |
-E | 启用扩展表达式 |
-h | 匹配查询模式的文件名 |
-i | 忽略大小写 |
-l | 只输出包括匹配行的文件名 |
待匹配字符串特殊格式 | 意义 |
---|---|
[:alnum:] | 字母与数字字符 |
[:alpha:] | 字母 |
[:ascii:] | ASCII字符 |
[:blank:] | 空格/制表符 |
[:cntrl:] | ASCII控制字符 |
[:digit:] | 数字 |
[:graph:] | 非控制、非空格字符 |
[:lower:] | 小写字母 |
[:print:] | 可打印字符 |
[:punct:] | 标点符号字符 |
[:space:] | 空白字符,包括垂直制表符 |
[:upper:] | 大写字母 |
[:xdigit:] | 16进制数字 |
常用扩展表达式(在选项启用-E之后) | 意义(记匹配次数 = index) |
---|---|
? | index <= 1 |
* | index >= 0 |
+ | index >= 1 |
{n} | index == n |
{n,} | index >= n |
{n,m} | n <= index <= m |
2.4.5 常用扩展
(…)代表任意内容
扩展 | 意义 |
---|---|
$(…) | 执行并返回执行结果 |
$((…)) | 算术表达式替换 |
参数扩展 | 意义 |
---|---|
${i} | 可用i的值替换${i} |
${#i} | 给出i的长度 |
${i%w} | 找到 i 中最后一个匹配的 w,返回 删除w后 的值 |
${i%%w} | 找到 i 中第一个匹配的 w,返回 删除w后 的值 |
${i#w} | 找到 i 中第一个匹配的 w,返回 删除w后 的值 |
${i##w} | 找到 i 中最后一个匹配的 w,返回 删除w后 的值 |
#!/bin/sh
a=who
echo a #输出:who
b=$(who)
echo b #输出:你的用户名 :0 你的时间 (:0)
c=0
echo c #输出:0
c=$(($c+1))
echo c #输出:1
i=/usr/local/etc/local/
echo ${i%local} #输出:/usr/local/etc/
echo ${i%%local*} #输出:/usr/
echo ${i#*local} #输出:/etc/local/
echo ${i##*local} #输出:/
exit 0