shell

变量相关

  • 可以使用echo打印变量值,格式如echo $name
  • 申明变量采用键值对的方式,如key=value。不能含有空格
  • 可以使用unset取消一个变量
  • env命令打印出当前的所有环境变量
  • set命令打印出当前的所有自定义变量
  • 环境变量和自定义变量的区别在于能不能被子进程所采用。当在bash中执行一条命令时,比如说ls -l命令。bash所在进程会fork一个子进程,然后子进程exec跟ls -l命令相关的程序;这时候,如果不去特别指定环境变量,那么子进程默认继承父进程的环境变量,而不继承用户自定义的变量。
  • 使用export命令可以使一个自定义变量成为环境变量
  • 可以调用read命令(是shell命令,不是系统调用)读取键盘输入
  • declare用来申明变量,通用格式如下:declare 【-aixr】variable;-a将后面的变量名申明为一个数组,-i将变量申明为一个整数,-x将后面的变量申明为环境变量,-r表示将变量申明为不可更改,只读类型。

管道相关命令

  • cut命令用来提取出一段信息中的一小段,常用的格式为cut -d '分割字符' -f [index]和cut -c start-end。第一种是将一段字符串按照分隔符分成若干段,取出第index段;第二种是以字符为单位,选定一定范围内的字符。通常配合管道一起使用
  • grep命令用来分析一整行信息。通用格式为grep [-acinv] [--color=auto] '查找的字符串' filename。-i表示忽略大小写,-a表示将二进制文件看成text的格式,-c统计所找字符串出现的次数,-n输出行号

常用命令

  • "#"相当于注释
  • 第一行#!/bin/bash表示此脚本所使用的shell是哪一种
  • 可以使用$((计算式))的方式来计算加减乘除
  • 执行sh脚本时,可以传递参数;这和c相类似,第一个参数表示文件名
  • $1-9表示脚本参数
  • $0表示脚本名称
  • $#表示一共有几个参数
  • $?表示一条命令执行完的返回值,返回的是最近一条命令的返回值
  • wc命令通常用来一个文件的文本信息,-c表示统计字符,-l表示统计行数
  • read命令的几个选项含义如下:-n表示限定输入的字符数,-s表示不显示输入的内容,-p表示可以接收多个参数。比如说要通过read命令接收三个参数:
read -p "请输入三个参数: " arg1 arg2 arg3
  • echo命令用于在标准输出上输出后面的所有参数,-n选项表示输出完不换行,-e可以不输出转义字符;当参数中出现以下一些特殊字符时,带-e选项的echo不会输出普通文本,而是按照特殊功能进行显示。
字符 作用
\a 发出警告声
\b 删除前一个字符
\c 最后不加上换行符
\f 换行但光标仍停留在原来的位置
\n 换行且光标移至首行
\r 光标移至首行但不换行
\t 插入tab
"\" 插入\
" 插入"
  • 系统的环境变量可以使用env命令查看,保存于/etc/profile文件中,这是系统的默认Shell配置文件。在每一个用户登录时会自动执行该文件,所以说这个配置文件对所有的用户都生效。而每个用户可以配置自己的配置文件,一般是$HOME/.bashrc文件。
  • 环境变量又分为全局的和局部的。局部环境变量只能用于当前shell,而全局的可以在任意一个shell中使用。
    使用命令set可以查看所有本地环境变量,使用export参数可以声明全局环境变量。
  • 可以使用declare 命令来声明变量,-i表示声明一个整数,-a定义一个数组,-x设置全局环境变量,-r定义只读变量。比如要声明一个数组,可以这样写
declare -a arr;arr[1]=1;arr[3]=2;
echo ${arr[3]}   //输出2
  • 使用source命令可以使声明的变量立即生效
  • unset命令可以取消一个环境变量
  • grep命令的基本格式如下,如果grep命令不指定文件,那么就从标准输入中去读取数据进行匹配。-c选项只显示符合样式的行数,-h选项不显示文件名,-i选项不区分大小写,-n选型显示匹配行及行号,-E关心大小写(默认不区分大小写)。匹配样式中可以用正则表达式且可以查找多个匹配,用|分隔。
    grep [选项][匹配样本][文件列表]
  • grep常用命令使用示例如下
#文件或者目录搜索
ls -l | grep "dirname"
#文件中查找特定字符
ls -l | grep "filename" | grep "str"
#检索特定进程
ps -aux | grep "processname"

特殊符号和通配符

  • 在shell中一部分字符被当做特殊字符,当输出他们的时候,不会输出普通字符,比如说$和\等
  • 当我们用单引号去输出参数的时候,就会把单引号里面所有的内容全部当成普通字符
  • 当我们用双引号去输出参数的时候,除了$,\等特殊字符之外的字符被当做普通字符输出
  • 当我们用倒引号输出的时候,会将倒引号中的字符当做命令去执行,将执行结果返回,比如说下面的语句就打印出了当前工作目录
echo "当前工作目录是:" `pwd`
  • 常用通配符及其功能
常用正则表达式 作用 示例表达式
* 匹配任意个字符,可以为0或多个 a*b
? 匹配一个字符 a?b
[list] 匹配list中的一个字符 a[abc]b
[^list] 匹配除list中的任意一个字符a[^abc]b
[c1-c2] 匹配c1到c2之间的所有字符,字符序列必须连续,如a-c a[1-5]b
. 匹配任意一个字符 .*abc
x\{m\} 字符x重复出现m次 x\{3\}
x\{m,\} 字符x至少出现m次 x\{3,\}
x\{m,n\} 字符x重复出现m到n次 x\{2,5\}
  • {}可以区分一个变量名,$()可以执行命令

逻辑控制语句

  • if...then,fi表示结束if
#单个条件判断
if [条件判断];then
     处理
fi
#多个条件判断
if [条件1]
then
    处理1
elif[条件2]
then
    处理2
else
    处理3
fi
  • 测试命令的基本结构如下,expression是表达式,表达式可以是数字,字符串,文件属性和各种类型的比较。test命令的返回值只能是整数,不能是其他类型。
test expression
  • 另外可以使用[]代替test命令,对于一般的逻辑条件判断效果一样;而test命令可以用来判断一些文件的属性,test命令的关于一些文件的选项如下表
test命令选项 作用
-e 判断文件是否存在
-f 判断文件是否存在且是否是文件
-d 判断文件是否存在且是否是目录文件
-c 判断文件是否存在且是否是设备文件
-S 判断文件是否存在且是否是socket文件
-p 判断文件是否存在且是否是管道文件
-L 判断文件是否存在且是否是链接文件
-nt test file1 -nt file2判断文件1是否比文件2新
-ot test file2 -ot file2判断文件1是否比文件2旧
-rwx test -[rwx] file判断文件相关的读写执行权限
  • 关于条件判断时经常会涉及一些整数之间的比较,不能使用大于小于号,因为bash会误以为是重定向符号,常见的符号如下表
符号 作用
test n1 -eq n2 判断数字1和数字2是否相等
test n1 -ge n2 判断数字1是否大于等于数字2
test n1 -gt n2 判断数字1是否大于数字2
test n1 -le n2 判断数字1是否小于等于数字2
test n1 -lt n2 判断数字1是否小于数字2
test n1 -ne n2 判断数字1是否不等于数字2
  • 当要对多个表达式进行判断的时候,情况如下表
运算符 作用
!exp 如果exp为假,则返回真
exp1 -a exp2 如果两个表达式同事为真,返回真
exp1 -o exp2 如果两个表达式中有一个为真,返回真
  • case多条件分支结构,示例代码如下,*)相当于default
echo -n "输入一个数:"
read n
case $n in
1)...
2)...
....
5)...
*)...
esac
  • select选择结构,示例如下
select choice in 1 2 3 4 5
do
    break
done
echo "you choose No.$choice"

循环结构

  • for循环的基本形式如下
for 变量 in 列表
do
  commands
done

#示例,用来遍历目录
for file in $(ls /home)
do
    ...
done
  • C式for结构,基本形式如下
for((exp1;exp2;exp3))
do
    ...
done

#示例
for((i=1;i<=10;i++))
do
    echo $i
done
  • while结构的基本格式如下
while test expression
do
    ...
done

#示例
index=1
while [ $index -le 6 ]
do
    echo $index
    let index++
done
  • 可以使用break跳出循环。另外,break n表示跳出n层循环,默认为1;continue继续下一次循环,与类c语言相似

函数和数组

  • 函数的定义格式如下,函数名称在同一个脚本文件中必须是唯一的,在函数调用时,bash会按照顺序去执行语句
function name
{
    commands
}
#或者可以省略function关键字,用括号代替
name()
{
    commands
}
  • 调用函数的方式与调用命令类似,直接写函数名就行,后面可以带上参数。这与在命令行执行命令或者调用可执行程序类似。在函数中使用传进来的参数的方法和调用脚本参数类似。大致规则如下
  • $0表示函数名
  • $1表示第一个参数,以此类推且最多能传进来9个参数
  • $#表示一共传进来几个参数
  • 同样的,$?记录最后执行的函数的返回值;而函数在不显示返回值的时候,默认返回函数中最后一条调用的命令的返回值;如果想要自定义返回值,使用关键字return,使用return命令的返回值只能在0-255之间
  • 有关同一个脚本范围内的局部变量和全局变量,是这样规定的:不显示调用local关键字声明的变量就是全局变量;相反,通过local声明的变量就是局部变量,只能在函数范围内使用
  • 数组的相关规则如下
#数组的声明方式如下
arr=(1,2,3,4,5)
#也可以使用declare关键字声明
declare -a arr=(1,2,3,4,5)
#使用一个数组变量的格式,下标从0开始,shell中的数组没有越界的概念。如果超过了范围,输出为空
${arr[1]}
#表示数组的所有元素
${arr[*]}
#表示数组的长度
${#arr[*]}
  • 当数组作为函数的参数传递时,必须遵从以下两种规则
  • 当调用函数传入数组参数时,必须将数组中每个元素一个个传进去,常常使用"${arr[*]}"的格式
  • 在函数内部使用数组时,需要声明一个局部数组变量去接收数组,才能使用
  • 当数组作为函数返回值时,需要使用echo命令将数组中的每个元素返回(上面说过,如果没有return命令,默认返回最后一条命令的返回值);并且在使用这个返回的数组之前,同样需要声明数组变量去接收,然后才能使用。示例代码如下
arr=(1 2 3 4 5)
echo "arr[*]=${arr[*]}"
echo "the length of arr = ${#arr[*]}"
echo "arr[1]=${arr[1]}"
func1()
{
    local temp=($1)
    echo "total args = $#"
    echo "the array arg:${temp[*]}"
    echo "the array arg:$@"
    return 0
}

func2()
{
    local old=($1)

    for((i=0;i<${#old[*]};i++))
    {
        old[$i]=$[${old[$i]}*2]
    }
    echo ${old[*]}
}

echo "函数中接收数组参数并输出"
func1 "${arr[*]}"

echo "函数中接受数组参数并将原值翻倍再返回回来输出"
newarr=`func2 "${arr[*]}"`
echo "newarr=${newarr[*]}"

文件处理相关命令

  • 一个外部设备首先需要挂载才能进行读取,挂载用的命令是mount,-t指定文件系统类型,通常不需要指定,操作系统会自动识别。一般格式如下,dest为指定的挂载目录,一般挂载目录都是新创建的空目录,因为当目录上新挂载一个文件系统时,该目录下的原文件都会被隐藏直到卸载该设备才会重新恢复。
mount /dev/sdax dest
  • fdisk命令可以查看电脑上的硬盘信息,以下命令可以查看所有硬盘分区信息
fdisk -l
  • 通过umount命令将设备卸载,命令如下
umount  /dev/sdax dest
  • 在执行一个shell命令行时,自动打开三个标准文件,标准输入,标准输出和标准出错。对应的文件描述符分别为0,1,2
  • 事实上,命令行就是一个进程;对于每一个进程,都有一个对应的文件描述符表,里面存放着进程的所有打开文件的文件描述符,而一个进程在初始状态下,自动会打开0,1,2三个文件描述符。
  • 输出重定向(>)首先会将文件截断为0,然后才向里面输出;相对的,追加重定向(>>)会在文件末尾接着输出
  • 1>表示重定向标准输出,2>表示重定向标准出错,&>表示将标准输出和标准出错合并重定向
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容