热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Shell脚本编程基础

通过本文记录学习LinuxShell的一些笔记思考和总结,以加强记忆和理解。主要学习参考资料有:1.《鸟哥的Linux私房菜-基础篇》第四版2.菜鸟教程——Linux教程3.ear

通过本文记录学习Linux Shell的一些笔记思考和总结,以加强记忆和理解。主要学习参考资料有:

1.《鸟哥的Linux私房菜-基础篇》第四版

2.菜鸟教程——Linux教程

3.earnxinyminutes——速成bash

4.C语言中文网——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=7 echo ${Variable:0:Length} # 这样会仅返回变量值的前7个字符 # 变量的默认值 echo ${Foo:-"DefaultValueIfFooIsMissingOrEmpty"} # 对 null (Foo=) 和空串 (Foo="") 起作用; 零(Foo=0)时返回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=10
b=20
val=`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=(
value0
value1
value2
value3
)

# 还可以单独定义数组的各个分量
array_name[0]=value0
array_name[1]=value1
array_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 name
echo 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 true
fi

# 形式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 true
elif [ expression 2 ]
then
   Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
   Statement(s) to be executed if expression 3 is true
else
   Statement(s) to be executed if no expression is true
fi


# 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 语句中使用 && 和 || 需要多对方括号 if [ $Name == "Steve" ] && [ $Age -eq 15 ] 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 command
do
   Statement(s) to be executed until command is true
done


#--------------------函数-------------------------------------
#在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


#--------------------其他-----------------------
# 表达式的格式如下:
echo $(( 10 + 5 )) # 与其他编程语言不同的是,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 2> "error.err" python hello.py > "output-and-error.log" 2>&1 python hello.py > /dev/null 2>&1 # > 会覆盖已存在的文件, >> 会以累加的方式输出文件中。 python hello.py >> "output.out" 2>> "error.err" # 覆盖 output.out , 追加 error.err 并统计行数 info bash Basic Shell Features Redirections > output.out 2>> error.err wc -l output.out error.err # 运行指令并打印文件描述符 (比如 /dev/fd/123) # 具体可查看: 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 的最后 10tail -n 10 file.txt # 打印 file.txt 的前 10head -n 10 file.txt # 将 file.txt 按行排序 sort file.txt # 报告或忽略重复的行,用选项 -d 打印重复的行 uniq -d file.txt # 打印每行中 , 之前内容 cut -d , -f 1 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 man 1 bash man bash # 用 info 指令查阅命令的 info 文档 (info 中按 ? 显示帮助信息) apropos info | grep ^info.*( man info info info info 5 info # 阅读 Bash 的 info 文档: info bash info bash Bash Features info bash 6 info --apropos bash

Shell 脚本编程基础


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
author-avatar
风流小姑-娘
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有