Linux系统Shell脚本学习总结

        所有从事基于Linux开发工作的工程师,命令行控制是基本的操作形式,掌握各种Linux命令行是进行各种开发的基础,但是我们会发现:工作中会经常执行一连串有顺序的、规律的甚至是重复性强繁琐的命令行来实现我们要的操作,比如软件编译及版本发布、代码更新、文件操作、字符串操作等,如果是对多条目的操作,只是手动输入命令将会极大限制我们的开发效率,这时编写shell脚本会是很好解决这些问题的途径,下面我会将大家工作中经常用到的shell命令做一个总结,也算是对自己学习的一个记录吧。

一 Linux基本操作命令

1 文件管理

1.1 查看文件或目录

ls # 列出目录下的清单; 

cat # 连接显示文件内容 (可以是文件对应相对路径);

less/more # 分页显示文件内容,建议使用less,相比于more更方便; 

head # 显示文件头部,可指定行数,默认显示10行; 

tail # 显示文件尾部,可指定行数,默认显示10行; 

file # 显示文件类型; 

wc # 查看文件或统计信息; 

find # 查找文件或目录(常用命令:find $path -name $filename);

1.2 操作文件或目录

touch:创建新文件(可以直接使用vim/vi/gedit等编辑器直接创建) ;

mkdir:创建目录,可以利用 -r选项递归创建,利用-p选项实现多层目录的创建;

cp: 拷贝命令,拷贝目录时可以使用 -r 选项实现递归拷贝,使用-f可实现强制拷贝,这样不会遗漏文件和对重名文件的覆盖;

ln: 创建链接命令,分为软连接和硬链接;

mv: 移动文件或者目录的命令,同时也是改名命令 ;

rm: 删除命令,-r 删除目录, 谨慎使用;

1.3 管理文件或目录权限

ls -l : 可以列出文件和目录的权限信息; 

chmod: 修改文件和目录的权限(需要了解字母及数字权限表示); 

chown/chgrp: 改变属组和属主;

setuid/setgid:设置用户或组权限位;

2 文本处理命令

sort : 文本排序 

uniq : 文本去重 

tr : 替换命令 

grep : 查找字符串(常用命令:grep -rn $filenamepath "$grepstr")

diff: 文件对比,找出文件差异

3 其他常用命令

hostname : 查看主机名 

w, who : 列出系统登录的用户 

uptime : 查看系统运行时间 

uname : 查看系统信息 

date : 显示和设置系统日期和时间 

id : 显示用户属性

paster : 合并文本 

dd : 备份和拷贝文件(和vim 和剪切命令一样) 

tar : 打包和解包文件 

mount, umount : 挂载和卸载存储介质 

df : 报告文件系统磁盘空间利用率 

du : 评估文件空间利用率 

ps : 查看系统的进程 

pidof : 列出进程的pid 

top : 相当于 Linux 的任务管理器 

& : 将作业后台运行 

jobs : 查看作业 

bg : 让挂起的进程在后台继续执行 

fg : 将后台进程放入前台 

fdisk: 查看系统的磁盘信息

二 Shell脚本基本语法

1 脚本运行初始

#!/bin/bash
echo "hello world"

说明:从hello world 起步,第一行的 #! /bin/bash 则是指定解释器,既然shell是门解释性语言,自然需要解释器,类似的,如果是 python脚本,则是 #! /bin/python 可能还需要一些编码格式的规定(utf-8),如果没有指定解释器,默认选择 sh ; 同时还需要给文件可执行权限,否则会报错,虽然我们一般把shell 脚本文件命名为 .sh 的文件(在Linux中文件后缀只能起到标识的作用,没有实际意义)

2 注释

单行注释:在shell中注释的符号是 “#”;

多行注释:起始语句:“:<

3 变量

在shell中设置变量和平时在命令行设置变量是一样的,可以直接定义一个变量,例如: a=10 不需要声明类型,不需要分号;

如果需要明确指定变量的类型的话,可以只用declare的选项指定类型;

变量的作用域: 在shell 中,变量默认都具有全局属性,如果需要局部的变量则需要在变量的声明处加 local 关键字。如: local a=10

变量的操作:

3.1 获取变量的值 在命令行获取变量的值是通过 echo ${a} 打印变量的值到终端的,那么echo的作用是打印,'${}' 的作用不言而喻(花括号可省略,起分割的作用)。

3.2 变量的运算 let a+=1 即使用 let 命令,当然除了 let 命令还有 '(())' 双括号,都可以进行变量的运算;

3.3 参数变量 说到shell的参数,有两个点,一个是命令行参数,一个是函数的参数,这里先说明命令行参数,函数的参数在后面学习函数的时候补充; 首先,记住这几个特殊符号: $# $@ $* $1 $2 ... 在运行程序的时候,经常需要带一些初始的参数,那么这些命令行参数到底是怎么传递进来的呢?

./shell_file.sh p1 p2 p3(shell脚本运行传入的三个参数,在具体代码中进行调用,可以是变量也可以是具体的字符串)

shell文件内的引用方法如下:

$# : 除$0以外的参数的个数(文件名,命令除外,它们用$0查看);

$@/*: 表示所有参数的集合 ;

$0,1,2...: 表示参数;

3.4 环境变量和普通变量

首先,明确两点,第一点即环境变量和普通变量在虚拟地址空间的存放位置,环境变量在栈顶的位置(高地址处),而普通变量是在数据段存放的;第二点,子进程会继承父进程的环境变量; 普通变量的命令行声明: a=10 将普通变量变为环境变量:export a 如何验证?

在父bash 中声明变量 a=10, 命令行敲 'bash' 命令相当于起了一个子bash, 在子 bash 中查找是否有 a变量;(set 命令查看所有变量, env 命令查看所有环境变量,exit或者ctrl + d 退出子bash)

在父bash 中将变量 a 声明为环境变量 'export a', 在子bash 中查看变量 a;

4 条件语句

shell的条件语句其实和C/C++/java差不多,具体的差异就在于语法格式的一些差别

4.1 if条件语句

不同于C的是,bash的条件测试不单单只是可以通过if进行判断,还要结合一些特殊的符号,命令和参数;

先列出基本的if语句的使用格式:

if true
then
    echo "This is true!"
else
    echo "This is false!"
fi 

:这就是 if 语句的基本使用格式,当然,中间还可以有 ’ elif ’ 相当于 C 的 else if ; 值得注意的是开始的 then 和 最后的 fi , 每个 if 都必须有一个fi 与之对应代表结束,因为没有了 ’ {} ‘;

前面说了,shell的条件判断需要结合一些命令,符号,选项来配合使用;

2.1 '[]' 和 test

'[]' 和 test 都被用作测试,如:
if [ -f install.log ]
then
    echo "install.log file exist!"
fi

test -f install.log; echo "install.log file exist!"

’ [ ] ’ 和 test 有很多选项,这里我就不一一演示,需要的话直接 man test; ( 注意: 使用 ‘[ ]’ 时, 需要两个空格,‘[’的后面, ‘]’的前面各一个);

不但这些,还有比较的符号;其中又分字符串和算数的不同;

字符串比较符号:= != \< \> -z -n

=         等于,如:if [ "$a" = "$b" ] 
==       等于,如:if [ "$a" == "$b" ],与=等价 
       注意:==的功能在[[]]和[]中的行为是不同的,如下: 
       1 [[ $a == z* ]]    # 如果$a以"z"开头(模式匹配)那么将为true 
       2 [[ $a == "z*" ]] # 如果$a等于z*(字符匹配),那么结果为true 
       3 
       4 [ $a == z* ]      # File globbing 和word splitting将会发生 
       5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true 
       一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是. 
       但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像. 
!=       不等于,如:if [ "$a" != "$b" ] 
       这个操作符将在[[]]结构中使用模式匹配. 
<       小于,在ASCII字母顺序下.如: 
       if [[ "$a" < "$b" ]] 
       if [ "$a" \< "$b" ] 
       注意:在[]结构中"<"需要被转义. 
>       大于,在ASCII字母顺序下.如: 
       if [[ "$a" > "$b" ]] 
       if [ "$a" \> "$b" ] 
       注意:在[]结构中">"需要被转义. 
       具体参考Example 26-11来查看这个操作符应用的例子. 
-z       字符串为"null".就是长度为0. 
-n       字符串不为"null" 
       注意: 
       使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z 或者就是未用""引用的字符串本身,放到[]结构中。虽然一般情况下可 以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯

算术比较符号: -eq -ne -le -ge -lt -gt

-eq       等于,如:if [ "$a" -eq "$b" ] 
-ne       不等于,如:if [ "$a" -ne "$b" ] 
-gt       大于,如:if [ "$a" -gt "$b" ] 
-ge       大于等于,如:if [ "$a" -ge "$b" ] 
-lt       小于,如:if [ "$a" -lt "$b" ] 
-le       小于等于,如:if [ "$a" -le "$b" ] 
<       小于(需要双括号),如:(("$a" < "$b")) 
<=       小于等于(需要双括号),如:(("$a" <= "$b")) 
>       大于(需要双括号),如:(("$a" > "$b")) 
>=       大于等于(需要双括号),如:(("$a" >= "$b"))

注:字符串的比较使用 ‘[]’ 时需要对 ><进行转义,所以shell提供 ’ [[ ]] ’ 符号,则不再需要转义,对于算术,shell提供 ’ (( )) ’ 则可以直接使用比较符进行比较

5 && 和 ||

&& : &&符号的前面的表达式为真才会执行 &&后面的表达式,也可表示为且&&表达式前后必须同时满足;

|| : || 符号前面的表达式为假才会执行 || 后面的表达式,也可表示为或||表达式前后有一个满足即可;

'!': 逻辑非

通常 && 和 || 配合使用

6 Case语句

shell的case语句的格式如下:

case $1 in 
1)
    echo "1"
    ;;
2)
    echo "2"
    ;;
esac

上面就是case语句的格式,这里刚好提醒一点,就是在shell中,不允许出现空语句,如果非要有空语句,则必须写上一个 冒号 ’ : ‘;

7 循环语句

7.1 for循环

for i in $(seq 10)
do
    echo -n $i
done

# 类C 的for 循环:

for (( i=0; i<10; ++i ))
do
    echo -n $i
done

说明: seq 是生成连续序列的命令,而shell中执行命令的话,会用 ’ $() ‘; 
echo -n 选项则是取消换行,每个echo语句都会带一个换行,直接一个echo则代表换行;

7.2 while循环

i=1
while true
do
    if [ $i -gt 2 ];then
        echo $i
        break
    fi
    let i++
done

8 函数

8.1 函数的定义

function  fun()
{
    if [ $# -ne 2 ];then
        return 1
    fi
    local a=$1
    local b=$2
    let c = a + b
    echo "hello $c"
    return 0
}

8.2 函数的调用

fun 1 2
if [ $? -ne 0 ];then
    echo "arguments fault!"
    exit
else
    echo "used right"
fi

上面就是一个简单的脚本,起作用是调用一个fun函数,判断调用是否正确;

说明: 从这个脚本中我们可以看出shell脚本函数的使用方式,从定义到参数的获取,再到返回值;最后还有函数的调用方式其实和命令的执行方式是一样的;

(注: function关键字可以省略但不建议,return 可以返回的值是 0-255)

9 重定向

重定向是将一个命令的输出结果作为下一个命令的输入,而重定向是将输出和文件相链接的;

重定向分为输入重定向和输出重定向,其中又有追加和覆盖的区别,总的来说就是下面四个符号:

’ > ‘, ’ >> ‘, ’ << ’ , ’ < ‘;

9.1 输出重定向

命令行语句 > 覆盖输出执行结果到指定文件

命令行语句 >> 追加输出执行结果到指定文件

9.2 输入重定向

tr a-z  A-Z <

说明: 这里的END不是固定的,只是起一个标签的作用,代表下次遇到END就结束输入;

重定向的这种用法还被用到项目中的configure文件,使configure文件可以自动生成Makefile文件

10 从标准输入读取

只是一个read的使用,在shell中使用read从标准输入读取数据

三 sed工具的使用

3.1 sed工具

sed 是一个文本处理工具,它为我们提供了很多的方便

3.2 sed的工作方式

sed是一行一行处理文本的,还有需要知道sed有一个HOLD空间和模式空间,HOLD用来作为文档处理的暂存空间,不能有任何的操作,所有的操作只能在模式空间进行;

sed常用的选项:

-e: 它告诉sed将下一个参数解释为sed指令,即需要连续多个处理时使用;

-f : 指定由sed指令组成的脚本的名称;

-i : 直接在读取的内容进行修改,如果没有-i,不会源文件造成任何修改;

-n: 静默模式,即只输出匹配的行,如果没有-n则匹配行会和源文件全部输出;

现在先不做演示,等把下面的编辑命令也复习完毕,一块做演示; sed的编辑命令有24个之多,在这里只学习常用的几个:

追加(a),更改(c),删除(d),插入(i),替换(s),打印(l),打印行号(=),转换(y);

3.3 常用sed处理命令

sed -n '/str/p' filepath #获取filepath文件内容中字符串str所在行的内容
sed -n 'nump' str.txt #获取文件str.txt第num行的内容
sed -i "s/oldstr/newstr/g" filepath #将filepath文件内容中的字符串oldstr替换成字符串newstr
echo $str | sed 's/\(.*\)str1\(.*\)str2\(.*\)/\2/g' #提取字符串str中str1和str2之间的字符串
sed -i "'$m'c ${m_line}" str.txt #在文件str.txt的第$m行写入${m_line}的内容
stat "str.txt" | sed -n '6,1p' | awk '{print $2, $3}' | sed -e 's/[-: ]//g' #获取文件str.txt的修改时间

四 其他有用的脚本语句

以下是本人在长期开发自动化运维脚本总结的还会经常用到的处理语句

cat file | wc -l #获取文件file的行数
${str%str1*} #获取字符串str中str1左边的所有字符串
${str##*str1} #获取字符串str中str1右边的所有字符串
#多进程执行(适用于需要循环处理大量数据的情况,且每个循环任务的执行都是独立的)
#允许的进程数
THREAD_NUM=500 #这里设置为了500
#定义描述符为9的管道
mkfifo tmp
exec 9<>tmp
#预先写入指定数量的换行符,一个换行符代表一个进程
for ((k=0;k<$THREAD_NUM;k++))
do
    echo -ne "\n" 1>&9
done
#循环体{
    #进程控制
    read -u 9
    {
        echo -ne "\n" 1>&9
    }&
}
wait
rm tmp

先整理这么多,如有遗漏还请指出

你可能感兴趣的:(脚本处理,Linux,shell)