shell脚本编程基础

参考菜鸟教程,把shell编程总结下。

编辑和运行shell脚本

编辑

编辑器:vim pycharm vscode等等能够编写代码的文本编辑器

运行

解释器:Linux 的 Shell 种类众多,常见的有:

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)

运行方式一般有两种:

  • 在代码开头加上默认的解释器,如
#!/usr/bin/env bash

然后将shell脚本文件改为可执行文件

chmod +x xx.sh

就可以直接用

./xx.sh #当前路径是必须写出来的,因为$PATH中并没有当前路径,shell找不到

运行了。

shell变量

命名规则

  • 只由(大写、小写)英文字母,数字,下划线组成
  • 不能用数字开头
  • 不能使用bash保留的关键字,可使用
bash -c help

查看所有关键字。

建改删用

  • 创建一个没有的shell变量
my_var="good" #不要在等式两边留有任何空格
  • 改变一个已有的shell变量

(1)改变量的值

my_var="good"
my_var="bad"  #改为“bad”了

(2)改权限

my_var="good"
readonly my_var #改为只读,这样就不能被修改,也不能被删除
  • 删除一个已有的变量
my_var="good"
unset my_var
  • 使用变量的值
my_var="good"
echo this is a ${my_var} day. #加上花括号,限定变量名的界限,以免引起混乱

shell字符串

  • 单引号中的所有字符都保持原样,不涉及转义或取变量的值
  • 双引号中涉及转义和取变量的值
  • 也可以不用引号
  • 拼接字符串:
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting  $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2  $greeting_3

输出为:
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !

注意第三个使用单引号的拼接方式

  • 获取字符串长度
your_name="runoob"
echo ${#your_name} # 6
  • 字符串切片
string="runoob is a great site"
echo ${string:1:4} # 输出unoo,即从编号1开始的4个字符,注意shell的字符串从0开始编号,这一点和python一致
echo ${string:2} # 输出noob is a great site,即从编号2开始的所有字符
  • 字符串查找
string="runoob is a great site"
echo `expr index "${string}" io`  # 输出4,即i或者o最开始出现的地方,注意这时候index从1开始计算,而不是0

shell数组

  • 定义方法
    (1) 使用空格作为分隔符
array_name=(value0 value1 value2 value3)
echo ${array_name[0]}  # 输出value0

(2)使用换行作为分隔符

array_name=(
value0
value1
value2
value3
)

(3) 直接对下标进行赋值,注意shell数组的编号可以不连续,有什么就用什么,没有的下标也可以取值,但是是空的

array_name[0]=value0
array_name[1]=value1
array_name[5]=value5
echo ${array_name[@]}
echo try 2
echo ${array_name[2]}
echo try 5
echo ${array_name[5]}

输出为:
value0 value1 value5
try 2

try 5
value5

  • 长度
array_name[0]=value0
array_name[1]=value1
array_name[5]=value5
# 取得数组元素的个数
length=${#array_name[@]}
echo first length: ${length}
# 或者
length=${#array_name[*]}
echo second length: ${length}
# 取得数组单个元素的长度
length5=${#array_name[5]}
echo one string length: ${length5}

输出为:
first length: 3
second length: 3
one string length: 6

shell注释

  • 单行注释,使用#开头
  • 多行注释
:<<EOF   # 使用EOF
echo here is a comment
EOF

echo it is not a comment


:<<!    # 使用!
# 或者
length=${#array_name[*]}
echo second length: ${length}
# 取得数组单个元素的长度
length5=${#array_name[5]}
echo one string length: ${length5}
!

传递参数

  • $0表示文件名,$1表示第一个命令行参数,$2表示第二个命令行参数。。。
  • $#表示传到脚本的命令行参数个数
  • "$*"以一个单字符串显示所有向脚本传递的参数
  • "$@"以字符串数组显示所有向脚本传递的参数

运算

算术运算

Alt
注意: 算术运算可以如下写

#!/bin/bash

a=5
b=6

result=$[a+b] # 注意等号两边不能有空格
echo "result 为: $result" # 11

关系运算

Alt

布尔运算和逻辑运算

Alt
Alt

字符串运算

Alt
注意:>、<、==、!= 也可以进行字符串比较,只不过这个时候需要使用[[ ]]来进行条件判断,而且里面的逻辑运算要用&&和||,另外逻辑非!此时也可用

#!/bin/bash

a="heri"
b="here"
if [[ $a < $b ]]
then
	echo 'a<b'
else
	echo 'a>=b'
fi

if [[ $a == $b ]]
then
	echo 'a=b'
else
	echo 'a!=b'
fi

文件测试运算符

Alt

# 如果没有目录"TCGA/breast",就创建它
if [ ! -d "TCGA/breast" ]
then
    mkdir "TCGA/breast"
fi

打印命令

echo命令

输出字符串,自动添加换行符

  • 单引号不转义
echo 'ok, this is \"cp\".\n'
echo 'yes.'
#result:
#ok, this is \"cp\".\n
#yes.
  • 双引号转义",但是不转义\n
echo "ok, this is \"cp\".\n"
echo "yes."
#ok, this is "cp".\n
#yes.
  • -e 强制转义
echo -e "ok, this is \"cp\".\n"
echo "yes."
#ok, this is "cp".
#
#yes.

printf命令

输出字符串,不自动添加换行,但是格式化能力强

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
 
# format-string为双引号
printf "%d %s\n" 1 "abc"

# 单引号与双引号效果一样 
printf '%d %s\n' 1 "abc" 

# 没有引号也可以输出
printf %s abcdef

# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
printf %s abc def

printf "%s\n" abc def

printf "%s %s %s\n" a b c d e f g h i j

# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
printf "%s and %d \n" 
#result:
#1 abc
#1 abc
#abcdefabcdefabc
#def
#a b c
#d e f
#g h i
#j  
# and 0

shell函数

函数定义

#1:
demoFun(){
    echo "这是我的第一个 shell 函数!"
}

#2:
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum)) # 带return
}

参数和返回值

  • 函数返回值在调用该函数后通过 ? 来 获 得 , 需 要 立 即 保 存 , 否 则 就 不 能 再 看 到 了 。 当 有 r e t u r n 时 , r e t u r n 的 必 须 是 0 − 255 的 整 数 , ? 来获得,需要立即保存,否则就不能再看到了。当有return时,return的必须是0-255的整数, ?returnreturn0255?获得return的整数;当没有return时,$?获得函数最后一条命令运行成功与否的值,成功为0,不成功为1.
#!/bin/bash
function demoFun1(){
    echo "这是我的第一个 shell 函数!"
    return `expr 1 + 1`
}

demoFun1
echo $?

function demoFun2(){
 echo "这是我的第二个 shell 函数!"
 expr 1 + 1
}

demoFun2
echo $?
demoFun1
echo 在这里插入命令!
echo $?

# 结果:
# 这是我的第一个 shell 函数!
# 2
# 这是我的第二个 shell 函数!
# 2
# 0
# 这是我的第一个 shell 函数!
# 在这里插入命令!
# 0
  • 函数参数用${n}获取
  • 函数参数数目用$#获取

test命令

检查条件是否满足

  • 数值
num1=100
num2=100
if test $[num1] -eq $[num2]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi

Alt

  • 字符串
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
    echo '两个字符串相等!'
else
    echo '两个字符串不相等!'
fi

Alt

  • 文件
cd /bin
if test -e ./bash
then
    echo '文件已存在!'
else
    echo '文件不存在!'
    
fi

Alt

  • 多重条件
    Shell还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为:"!“最高,”-a"次之,"-o"最低。
cd /bin
if test -e ./notFile -o -e ./bash
then
    echo '至少有一个文件存在!'
else
    echo '两个文件都不存在'
fi

输入输出重定向

标准输入(stdin)的文件描述符为0,标准输出(stdout)的文件描述符为1,标准错误(stderr)的文件描述符为2。通过重定向,可以从文件读数据,并且输出到文件。

重定向标准输入,标准输出

  • 改写方式
wl -l < file > file2 # 从file中读取数据,返回行数, 如56 输出到文件file2,文件file2原来的内容会被覆盖
  • 追加方式
wl -l < file >> file2 # 从file中读取数据,返回行数, 如56 输出追加到文件file2末尾

重定向标准输出和标准错误到一个位置

wl -l < file > file2 2>&1 # 从file中读取数据,返回行数, 如56 输出到文件file2,如果命令出错,把出错信息返回到file2

交互式(多行)输入

$ wc -l << EOF  # 在shell中交互输入
    欢迎来到
    菜鸟教程
    www.runoob.com
EOF
3  # 返回命令结果

或者

#!/bin/bash

wc -l << EOF
    欢迎来到
    菜鸟教程
    www.runoob.com
EOF

不要显示输出

当不想要显示输出时,重定向到/dev/null

wl -l < file > /dev/null 2>&1

导入其他文件

封装公用部分为file,在其他文件中使用时,只需要导入这个shell文件就行了。有两种写法

. file
#或者
source file

第一个shell文件为

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

url="http://www.runoob.com"

第二个shell文件为

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

#使用 . 号来引用test1.sh 文件
. ./test1.sh

# 或者使用以下包含文件代码
# source ./test1.sh

echo "菜鸟教程官网地址:${url}"

流程控制

条件分支

  • if else模式
    有else或者没有else都行
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi # 终端命令提示符写法
# 或者脚本写法,把;用换行替换,一些关键字后的空格用换行缩进替换
if [ $(ps -ef | grep -c "ssh") -gt 1 ]
then
	echo "true"
fi
  • if else-if else模式
    想象一个二叉树,不断进行条件判断进行延伸
a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi

循环

  • for循环
array=(1 2 3 4 5)
for loop in ${array[*]}
do
    echo "The value is: $loop"
done
#或者
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
# 但是以下不行
for loop in (1 2 3 4 5)
do
    echo "The value is: $loop"
done
  • while循环
#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done
  • util循环
#!/bin/bash

a=0

until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done
  • 无限循环:三种方法
while :
do
    command
done
#或者
while true
do
    command
done
#或者
for (( ; ; ))
do
	command
done
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值