Shell 脚本编程基础
通过本文记录学习Linux Shell的一些笔记思考和总结,以加强记忆和理解。主要学习参考资料有:
1.《鸟哥的Linux私房菜-基础篇》第四版
一、shell脚本基础
#!/bin/bash # 脚本的第一行叫 shebang,用来告知系统如何执行该脚本: # 参见: http://en.wikipedia.org/wiki/Shebang_(Unix) # 如你所见,注释以 # 开头,shebang 也是注释。 #-------------Shell提示符($和#的区别)---------------# 普通用户的提示符是$,root用户的提示符是#su #切换到root用户(需输入密码)su - username #切换回普通用户 # 显示 “Hello world!” echo Hello world! # 每一句指令以换行或分号隔开: echo 'This is the first line'; echo 'This is the second line' #--------------变量定义和使用--------------# 定义变量三种方式(注意赋值符左右不能有空格!)variable=value #方式一 variable='value' #方式二 variable="value" #方式三 # 声明一个变量: Variable="Some string" # 下面是错误的做法: Variable = "Some string" # Bash 会把 Variable 当做一个指令,由于找不到该指令,因此这里会报错。 # 也不可以这样: Variable= 'Some string' # Bash 会认为 'Some string' 是一条指令,由于找不到该指令,这里再次报错。 # (这个例子中 'Variable=' 这部分会被当作仅对 'Some string' 起作用的赋值。) # 使用变量: echo $Variable #方式一echo ${Variable} #方式二(推荐) echo "$Variable" #方式三 echo '$Variable' #方式四(错误) # 当你赋值 (assign) 、导出 (export),或者以其他方式使用变量时,变量名前不加 $。 # 如果要使用变量的值, 则要加 $。 # 注意: ' (单引号) 不会展开变量(即会屏蔽掉变量)。 # 将命令的结果赋值给变量variable=`command` #方式一variable=$(command) #方式二(推荐) # 只读变量readonly variable # 删除变量unset variable_name #变量类型分三种,局部变量、环境变量、shell变量#特殊变量
变量 | 含义 |
$0 | 当前脚本文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
#变量替换
形式 | 说明 |
${var} | 变量本来的值 |
${var:-word} | 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。 |
${var:=word} | 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。 |
${var:?message} | 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。 若此替换出现在Shell脚本中,那么脚本将停止运行。 |
${var:+word} | 如果变量 var 被定义,那么返回 word,但不改变 var 的值。 |
# 在变量内部进行字符串代换 echo ${Variable/Some/A} # 会把 Variable 中首次出现的 "some" 替换成 “A”。 # 变量的截取 Length= :Length} # 这样会仅返回变量值的前7个字符 # 变量的默认值 echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"} # 对 )时返回0 # 注意这仅返回默认值而不是改变变量的值 # 内置变量: # 下面的内置变量很有用 echo "Last program return value: $?" echo "Script's PID: $$" echo "Number of arguments: $#" echo "Scripts arguments: $@" echo "Scripts arguments separated in different variables: $1 $2..." #-------------------Shell运算符----------------------#expr 是一款表达式计算工具,使用它能完成表达式的求值操作。表达式和运算符之间要有空格,完整的表达式要被 ` ` 包含
val=`expr 2 + 2` a=10b=20val=`expr $a + $b` #算术运算符列表
运算符 | 说明 | 举例 |
+ | 加法 | `expr $a + $b` 结果为 30。 |
- | 减法 | `expr $a - $b` 结果为 10。 |
* | 乘法 | `expr $a \* $b` 结果为 200。 |
/ | 除法 | `expr $b / $a` 结果为 2。 |
% | 取余 | `expr $b % $a` 结果为 0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ $a != $b ] 返回 true。 |
#关系运算符列表
运算符 | 说明 | 举例 |
-eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 true。 |
-ne | 检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
#布尔运算符列表
运算符 | 说明 | 示例 |
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
#字符串运算符列表
运算符 | 说明 | 示例 |
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否为0,不为0返回 true。 | [ -z $a ] 返回 true。 |
str | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
#文件测试运算符列表
运算符 | 说明 | 示例 |
-b | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-d file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是具名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
#----------------------字符串---------------------------# 单引号(所有字符都原样输出)str='this is a string' # 双引号your_name='qinjx'str="Hello, I know your are \"$your_name\"! \n" # 拼接字符串your_name="qinjx"greeting="hello, "$your_name" !"greeting_1="hello, ${your_name} !"echo $greeting $greeting_1 # 获取字符串长度string="abcd"echo ${#string} #输出 4 # 提取子字符串string="alibaba is a great company"echo ${string:1:4} #输出liba # 查找子字符串string="alibaba is a great company"echo `expr index "$string" is` #----------------Shell数组:shell数组的定义、数组长度----------------# 定义数组array_name=(value0 value1 value2 value3) # 或者array_name=(value0value1value2value3) # 还可以单独定义数组的各个分量array_name[0]=value0array_name[1]=value1array_name[2]=value2 # 读取数组# 读取数组元素值的一般格式是: ${array_name[index]}valuen=${array_name[2]} # 使用@ 或 * 可以获取数组中的所有元素${array_name[*]}${array_name[@]} # 获取数组的长度# 取得数组元素的个数length=${#array_name[@]}# 或者length=${#array_name[*]}# 取得数组单个元素的长度lengthn=${#array_name[n]} #------------------printf函数-------------------------# printf 命令的语法:printf format-string [arguments...] # 这里仅说明与C语言printf()函数的不同:# 1)printf 命令不用加括号# 2)format-string 可以没有引号,但最好加上,单引号双引号均可。# 3)参数多于格式控制符(%)时,format-string 可以重用,可以将所有参数都转换。# 4)arguments 使用空格分隔,不用逗号。 #--------------------读取变量--------------------------# 读取输入:echo "What's your name?" read Name # 这里不需要声明新变量 echo Hello, $Name! #方式二read -p "Enter your name:"read nameecho Hello,$name #--------------------if条件语句------------------------# Shell 有三种 if ... else 语句:# 1)if ... fi 语句;# 2)if ... else ... fi 语句;# 3)if ... elif ... else ... fi 语句。 # 形式1:if [ expression ]then Statement(s) to be executed if expression is truefi # 形式2:if [ expression ] then Statement(s) to be executed if expression is true else Statement(s) to be executed if expression is not true fi # 形式3:if [ expression 1 ]then Statement(s) to be executed if expression 1 is trueelif [ expression 2 ]then Statement(s) to be executed if expression 2 is trueelif [ expression 3 ]then Statement(s) to be executed if expression 3 is trueelse Statement(s) to be executed if no expression is truefi # if ... else 语句也经常与 test 命令结合使用num1=$[2*3]num2=$[1+5]if test $[num1] -eq $[num2]then echo 'The two numbers are equal!'else echo 'The two numbers are not equal!'fi # 通常的 if 结构看起来像这样: # 'man test' 可查看更多的信息 if [ $Name -ne $USER ] then echo "Your name isn't your username" else echo "Your name is your username" fi # 根据上一个指令执行结果决定是否执行下一个指令 echo "Always executed" || echo "Only executed if first command fails" echo "Always executed" && echo "Only executed if first command does NOT fail" # 在 if 语句中使用 && 和 || 需要多对方括号 ] then echo "This will run if $Name is Steve AND $Age is 15." fi if [ $Name == "Daniya" ] || [ $Name == "Zach" ] then echo "This will run if $Name is Daniya OR Zach." fi #------------------case分支语句----------------------------# Bash 的 case 语句与 Java 和 C++ 中的 switch 语句类似: case "$Variable" in # 列出需要匹配的字符串 0) echo "There is a zero.";; 1) echo "There is a one.";; *) echo "It is not null.";; esac
#------------------for循环、while循环、until循环---------------------# 循环遍历给定的参数序列: # 变量$Variable 的值会被打印 3 次。 for Variable in {1..3} do echo "$Variable" done # 或传统的 “for循环” : for ((a=1; a <= 3; a++)) do echo $a done # 也可以用于文件 # 用 cat 输出 file1 和 file2 内容 for Variable in file1 file2 do cat "$Variable" done # 或作用于其他命令的输出 # 对 ls 输出的文件执行 cat 指令。 for Output in $(ls) do cat "$Output" done #-------------------------------- # while 循环: while [ true ] do echo "loop body here..." break done #--------------------------------# until 循环until commanddo Statement(s) to be executed until command is truedone
#--------------------函数-------------------------------------#在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...,当n>=10时,需要使用${n}来获取参数。# 你也可以使用函数 # 定义函数: function foo () { echo "Arguments work just like script arguments: $@" echo "And: $1 $2..." echo "This is a function" return 0 } # 更简单的方法 bar () { echo "Another way to declare functions!" return 0 } # 调用函数 foo "My name is" $Name
#--------------------其他----------------------- # 表达式的格式如下: + )) # 与其他编程语言不同的是,bash 运行时依赖上下文。比如,使用 ls 时,列出当前目录。 ls # 指令可以带有选项: ls -l # 列出文件和目录的详细信息 # 前一个指令的输出可以当作后一个指令的输入。grep 用来匹配字符串。 # 用下面的指令列出当前目录下所有的 txt 文件: ls -l | grep "\.txt" # 重定向输入和输出(标准输入,标准输出,标准错误)。 # 以 ^EOF$ 作为结束标记从标准输入读取数据并覆盖 hello.py : cat > hello.py << EOF #!/usr/bin/env python from __future__ import print_function import sys print("#stdout", file=sys.stdout) print("#stderr", file=sys.stderr) for line in sys.stdin: print(line, file=sys.stdout) EOF # 重定向可以到输出,输入和错误输出。 python hello.py < "input.in" python hello.py > "output.out" python hello.py > "error.err" python hello.py > >& python hello.py > /dev/>& # > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。 python hello.py >> >> "error.err" # 覆盖 output.out , 追加 error.err 并统计行数 >> error.err wc -l output.out error.err # 运行指令并打印文件描述符 (比如 /dev/fd/) # 具体可查看: man fd echo <(echo "#helloworld") # 以 "#helloworld" 覆盖 output.out: cat > output.out <(echo "#helloworld") echo "#helloworld" > output.out echo "#helloworld" | cat > output.out echo "#helloworld" | tee output.out >/dev/null # 清理临时文件并显示详情(增加 '-i' 选项启用交互模式) rm -v output.out error.err output-and-error.log # 一个指令可用 $( ) 嵌套在另一个指令内部: # 以下的指令会打印当前目录下的目录和文件总数 echo "There are $(ls | wc -l) items here." # 反引号 `` 起相同作用,但不允许嵌套 # 优先使用 $( ). echo "There are `ls | wc -l` items here." # 有很多有用的指令需要学习: # 打印 行 file.txt # 打印 行 file.txt # 将 file.txt 按行排序 sort file.txt # 报告或忽略重复的行,用选项 -d 打印重复的行 uniq -d file.txt # 打印每行中 ',' 之前内容 file.txt # 将 file.txt 文件所有 'okay' 替换为 'great', (兼容正则表达式) sed -i 's/okay/great/g' file.txt # 将 file.txt 中匹配正则的行打印到标准输出 # 这里打印以 "foo" 开头, "bar" 结尾的行 grep "^foo.*bar$" file.txt # 使用选项 "-c" 统计行数 grep -c "^foo.*bar$" file.txt # 如果只是要按字面形式搜索字符串而不是按正则表达式,使用 fgrep (或 grep -F) fgrep "^foo.*bar$" file.txt # 以 bash 内建的 'help' 指令阅读 Bash 自带文档: help help help help for help return help source help . # 用 man 指令阅读相关的 Bash 手册 apropos bash bash man bash # 用 info 指令查阅命令的 info 文档 (info 中按 ? 显示帮助信息) apropos info | grep '^info.*(' man info info info info # 阅读 Bash 的 info 文档: info bash info bash 'Bash Features' info --apropos bash
二、shell脚本思维导图
Shell 脚本编程基础的更多相关文章
- Linux shell脚本编程基础之练习篇
shell脚本编程基础之练习篇. 1.编写一个脚本使我们在写一个脚本时自动生成”#!/bin/bash”这一行和注释信息. #!/bin/bash ] then echo "请输入一个参数& ...
- SHELL脚本编程基础知识
SHELL脚本编程基础知识 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Linux之父Linus有一句话很经典:"Talk is cheap, show me the ...
- shell脚本编程基础介绍
Linux系统——shell脚本编程基础介绍 1.什么是shell 它是一个命令解释器,在linux/unix操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种操作输出的结果 ...
- linux基础—课堂随笔_03 SHELL脚本编程基础
shell脚本编程基础 条件选择:if语句 选择执行: 注意:if语句可嵌套 单分支 if(开头)判断条件:then条件为真的分支代码 fi(结尾) 双分支 if(开头)判断条件:then条件为真的分 ...
- shell脚本编程基础
最近学习了shell脚本编程,感觉自己的脚本写的不太好,所以想把shell脚本相关的知识系统的整理一下,便于以后的学习和使用. 一.shell脚本基础 shell脚本是利用shell的功能 ...
- Linux Shell脚本编程-基础1
概述: shell脚本在Linux系统管理员的运维工作中非常重要.shell脚本能够帮助我们很方便的管理服务器,因为我们可以指定一个任务计划,定时的去执行某一个脚本以满足我们的需求.本篇将从编程基础 ...
- 《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---57
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- Linux基础篇–shell脚本编程基础
本章内容概要 编程基础 脚本基本格式 变量 运算 条件测试 配置用户环境 7.1 编程基础程序:指令+数据程序编程风格: 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心 ...
- Shell脚本编程基础笔记一
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/8176137.html 一:脚本文件的创建.格式.运行 1:创建shell脚本 首先,要创建一个文件 touch ...
随机推荐
- MyBatis的生命周期
MyBatis的生命周期 所谓的生命周期就是第一个对象应该存活的时间,比如一些对象一次用完后就要关闭,使它们被Java虚拟机(JVM)销毁,以避免继续占用资源,所以我们会根据每一个组件的作用去确定其生 ...
- dos2unix命令
dos2unix命令用来将DOS格式的文本文件转换成UNIX格式的(DOS/MAC to UNIX text file format converter).DOS下的文本文件是以\r\n作为断行标志的 ...
- Linux软件包的安装(rpm+yum)
概述: 1.rpm软件包管理命令软件包的获取a.光盘镜像中有很多软件包可以使用:先挂载光盘,再查看软件包b.从软件的官网获取 .rpm 安装rpm包 ipm -ivh 软件包名称删除rpm包 ipm ...
- IE8“开发人员工具”(下)
浏览器模式 说白了,就是让用户选择当前页面用何种IE版本去渲染. 文本模式 说起“文本模式”这个名词,这又要回到渲染页面的3种模式了:诡异模式(Quirks mode,也有翻译为兼容模式.怪异模式的) ...
- React篇-子组件调用父组件方法,并传值
react 中子组件调用父组件的方法,通过props: 父组件: isNote(data){} <div className="tabC01"> <FTab ta ...
- node跨域cors模块,nodejs+express跨域
使用express写的接口,只能在内部使用,如果想要外部的服务访问,就涉及到了跨域.但是又不想用jsonp,其实有一个node模块,可以轻松实现跨域 npm install cors --save 然 ...
- bootstrap modal与select2使用冲突解决
今天发现项目使用bootstrap modal 与 jquery select2 结合时发现select2不起作用,点击select框不显示选项,查阅资料后发现是因为modal层遮挡了select2的 ...
- Tensorflow 搭建神经网络及tensorboard可视化
1. session对话控制 matrix1 = tf.constant([[3,3]]) matrix2 = tf.constant([[2],[2]]) product = tf.matmul(m ...
- jupyter 快捷键
Jupyter Notebook 的快捷键 Jupyter Notebook 有两种键盘输入模式.编辑模式,允许你往单元中键入代码或文本:这时的单元框线是绿色的.命令模式,键盘输入运行程序命令:这时的 ...
- Kotlin sealed class
密封类的概念对于我这种从古代语言进化到现代语言的老古董来说还是有点绕腾的啊! 1. 密封类用来表示受限的类继承结构 解释:类中 元素值限制在某一个集合之中 2. 密封类可以有子类,但是所有的子类都必须 ...