shell编程

已"#"  作为注释, 除了 以"#!" 开头的。

"#!/bin/bash" 会告诉shell用哪个shell来运行脚本(必须要再第一行)

 

文本字符串和命令输出显示在同一行

shell文件

#!/bin/bash

echo  -n "The time and date are: "

date

打印 :The time and date are:Tue Apr  2 10:28:38 CST 2019

 

在shell脚本中,调用命令

shell文件

testParm1 = $(date)

testParm2 = `date`    //反引号,‘~’那个键

用例:

#!/bin/bash

today=$(date +%y%m%d)    //%y%m%d  --> 190402     +%Y%m%d  -->  20190402

ls /usr/bin -al > log.$today

 

Shell 传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数

#!/bin/bash

echo "Shell 传递参数实例!";

echo "执行的文件名:$0";

echo "第一个参数为:$1";

echo "第二个参数为:$2";

echo "第三个参数为:$3";

参数处理

说明

$#

传递到脚本的参数个数

$*

以一个单字符串显示所有向脚本传递的参数。

$$

脚本运行的当前进程ID号

$!

后台运行的最后一个进程的ID号

$@

与$*相同,但是使用时加引号,并在引号中返回每个参数。

$-

显示Shell使用的当前选项,与set命令功能相同。

$?

显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

重定向

 

输出重定向

可以将命令的输出重定向到另一个位置(比如文件)

  1.  '>'   '>>'     '>' 例如输出到文件,会执行覆盖操作;  '>>'  输出到文件会追加到文件末尾。

输入重定向

 

 


环境变量

env    printenv

显示变量

 

打印 echo $【变量名】 例:echo $JAVA_HOME

直接显示环境变量,对应的文件夹内容

[newcs@dsszbyz-etl-inf7 day]$ ll $JAVA_HOME

total 25928

drwxr-xr-x 2 root root     4096 Mar 16  2018 bin

-rw-r--r-- 1 root root     3244 Dec 20  2017 COPYRIGHT

drwxr-xr-x 4 root root      147 Mar 16  2018 db

drwxr-xr-x 3 root root     4096 Mar 16  2018 include

-rw-r--r-- 1 root root  5202881 Dec 20  2017 javafx-src.zip

drwxr-xr-x 5 root root     4096 Mar 16  2018 jre

drwxr-xr-x 5 root root     4096 Mar 16  2018 lib

-rw-r--r-- 1 root root       40 Dec 20  2017 LICENSE

drwxr-xr-x 4 root root       60 Mar 16  2018 man

-rw-r--r-- 1 root root      159 Dec 20  2017 README.html

-rw-r--r-- 1 root root      424 Dec 20  2017 release

-rw-r--r-- 1 root root 21095860 Dec 20  2017 src.zip

-rw-r--r-- 1 root root    63933 Dec 20  2017 THIRDPARTYLICENSEREADME-JAVAFX.txt

-rw-r--r-- 1 root root   145180 Dec 20  2017 THIRDPARTYLICENSEREADME.txt

 

设置局部用户定义变量

[newcs@dsszbyz-etl-inf7 ~]$ myParm="parm1"    //定义变量

[newcs@dsszbyz-etl-inf7 ~]$ echo $myParm

parm1

[newcs@dsszbyz-etl-inf7 ~]$ unset myParm            //删除变量

[newcs@dsszbyz-etl-inf7 ~]$ echo $myParm

 

[newcs@dsszbyz-etl-inf7 ~]$

定义数组

mytest=("one" "two" "three" "four"  "five")

${mytest[1]}  //two

 

//打印数组所有值

echo ${mytest[*]}

 

parm1=("day_id" "${v_dayid}")

parm2=("hour_id" "${v_hourid}")

parmlist=(${parm1} ${parm2})

 

 

 

追加环境变量 PATH

环境变量的本质是方便运行程序命令。  

例如,运行java。没有配置PATH时会报找不到的错误,必须要使用全路径才能找到。

多个路径是用“:”分割,追加在末尾时。

PATH = $PATH:【路径】

PATH变量的修改只能持续到退出或重启系统

 

环境变量持久化

/etc/profile.d目录中创建一个以.sh结尾的文件。把所有新的或修改过的全局环境变

量设置放在这个文件中。

在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。这一

点适用于所有类型的shell进程。

但如果设置了BASH_ENV变量,那么记住,除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放在别的地方

 


命令替换(常用与将命令输出赋给变量

命令替换会创建一个子shell来运行对应的命令

  • `命令`       反引号字符(`)

  • $(命令)     $()格式

 


数学运算

    1.expr 命令,使用诸多限制

    2.使用方括号  "$[数学表达式]" 

  • bash shell数学运算但只支持整数运算

  • z shell 提供了完整的浮点数算术操作

    3.bash计算器(bc)

[newcs@dsszbyz-etl-inf7 ~]$ bc

bc 1.06.95

Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.

This is free software with ABSOLUTELY NO WARRANTY.

For details type `warranty'.

3.5 / 3

1

scale=2

3.5 / 3

1.16

scale 默认 0 ,代表显示的小数位

使用变量

[newcs@dsszbyz-etl-inf7 ~]$ bc -q

var1 = 1

var2 = var1*0.123456

print var2

print var2

.123456

scale=3

print var2

.123456

var2 *100

12.345600

 

在shell脚本中,使用bc计算器

#!/bin/bash

var1=100

var2=45

var3=$(echo "scale=4; $var1 / $var2" | bc)

//var3=`echo "scale=4; $var1 / $var2" | bc`           命令替换

 

退出状态码

变量$?来保存上个已执行命令的退出状态,它的值会变成由shell所执行的最后一条命令

的退出状态码。

 

成功:0

结束时错误: 一个整数值

[newcs@dsszbyz-etl-inf7 ~]$ echo $?

0

[newcs@dsszbyz-etl-inf7 ~]$ dsf

-bash: dsf: command not found

[newcs@dsszbyz-etl-inf7 ~]$ echo $?

127

 

常见Linux退出状态码

状态码

 

0

命令成功结束

1

一般性未知错误

2

不适合的shell命令

126

命令不可执行

127

没找到命令

128

无效的退出参数

128+x

与Linux信号x相关的严重错误

130

通过Ctrl+C终止的命令

255

正常范围之外的退出状态码

 

退出状态码126表明用户没有执行命令的正确权限。

 


结构化编程

1.

if 【command】

then

【command】

fi

 

//格式2,和上相同

if 【command】;then

【command】

fi

 

2. 

if 【command】;then

【commands】

else

    【commands】

fi

 

3.

if【command】

then

【commands】

elif 【command】; then

【commands】

fi

判断命令的退出状态码为0 就执行 then中的内容

 

test 命令

条件成立,返回0 

 

格式一

if test 【条件】 ;then

【commands】

else

    【commands】

fi

 

格式二

if [条件] ;then

【commands】

else

    【commands】

fi

如果test 里的条件是变量,不为空返回0 ,

 

test支持可以三类判断条件:

 数值比较 (只能比较整数,小数会报错)

 字符串比较

 文件比较

 

数值比较

-eq

=

相等

-ge

>=

大于或等于

-gt

>

大于

-le

<=

小于或等于

-lt

<

小于

-ne

!=

不等于

字符串比较    

=

str1 = str2 

检查str1是否和str2相同

!=

str1 != str2  

检查str1是否和str2不同

<

str1 < str2  

检查str1是否比str2小

>

str1 > str2  

检查str1是否比str2大

-n

-n str1  

检查str1的长度是否非0 

-z

-z str1  

检查str1的长度是否为0

使用"<"、">" 时,要转义,不然容易被程序识别为重定向

 

文件比较

-d file  

检查file是否存在并是一个目录

-e file  

检查file是否存在

-f file  

检查file是否存在并是一个文件

-r file  

检查file是否存在并可读

-s file  

检查file是否存在并非空

-w file  

检查file是否存在并可写

-x file  

检查file是否存在并可执行

-O file  

检查file是否存在并属当前用户所有

-G file  

检查file是否存在并且默认组与当前用户相同

file1 -nt file2  

检查file1是否比file2新

file1 -ot file2  

检查file1是否比file2旧

 

并、或运算

if  [ 条件1] && [  条件2]

 

双括号命令

    if((操作))

    可包括test命令的(但使用 ">" 时不用转义),还有

val++ 

后增

val--  

后减

++val 

先增

--val  

先减

!  

逻辑求反

~  

位求反

**  

幂运算

<<  

左位移

>>  

右位移

&  

位布尔和

|  

位布尔或

&&  

逻辑和

||  

逻辑或

 

for循环

for 【变量名】 in 【变量组】 ;do

    【commands】

done

    

遍历目录

for file in /home/rich/test/*

do

if [ -d "$file" ]

then

echo "$file is a directory"

elif [ -f "$file" ]

then

echo "$file is a file"

fi

done

 

ps 将$file变量用双引号圈起来。如果不这么做,遇到含有空格的目录名或文件名时就会有错误产生。

 

c风格的for 

#!/bin/bash

for (( i=1; i <= 10; i++ ))

do

echo "The next number is $i"

done

$ ./test8

The next number is 1

The next number is 2

The next number is 3

 

for (( a=1, b=10; a <= 10; a++, b-- ))

 

 

until 直到

只有测试命令的退出状态码不为0,bash shell才会执行循环中列出的命令。一旦测试命令返回了退出状态码0,循环就结束。

 

break结束        后面可以跟参数    break 2 终止出第二层循环

 

 

处理循环的输出

for file in /home/rich/*

do

if [ -d "$file" ]

then

echo "$file is a directory"

elif

echo "$file is a file"

fi

done > output.txt

//done | sort        

 


处理用户参数

    命令行参数

参数会默认以空格区分,传字符串需用 单引号或双引号

 

校验命令行参数

    使用命令行参数时,一定要检查,否则容易报错。

校验方法1

if [ -n "$1" ]

then

echo Hello $1, glad to meet you.

else

echo "Sorry, you did not identify yourself. "

fi

 

校验方法2

    直接对比输入命令行参数个数

if [$# -ne 3];then

    //参数个数不等于3

else

---------------------------

if [$# -eq 3];then

    //参数个数等于3

else

---------------------------

if (( $# == 3)) ;then

echo "参数= 3"

else

echo "参数!= 3"

fi

 

获取最后一个命令行参数

${!#}  而不是 ${$#}  //暂时这种方法无效

params=$#

$params

 

获取所有参数

$*      将参数视为一个整体,而不是多个个体

$@    将参数当作同一字符串中的多个独立的单词

 

处理多个参数(日常函数的 处理方式)

getopt、getopts

https://linuxeye.com/389.html

 

 

获取用户输入(非命令行方式)

#!/bin/bash

echo -n "Enter your name: "

read name

echo "Hello $name, welcome to my program. "

 

#方法二:

 

read -p "Please enter your age: " age

days=$[ $age * 365 ]

echo "That makes you over $days days old! "

 

#!/bin/bash

echo -n "your name?"

read name

echo "you are $name"

 

read -p "your age" age

echo "your are $age years old"

echo -n // 打印后,不换行

read 

  • -p  指定单个或多个参数

  • -t   限定超时时长(秒)   超时未输入,返回非零的状态码

  • -n1

  • -s  不显示输入信息,比如密码(实际上只是将文本颜色设成跟背景色一样)

  • -a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。

  • -d 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。

  • -p 后面跟提示信息,即在输入前打印提示信息。

  • -e 在输入的时候可以使用命令补全功能。

  • -n 后跟一个数字,定义输入文本的长度,很实用。

  • -r 屏蔽\,如果没有该选项,则\作为一个转义字符,有的话 \就是个正常的字符了。

  • -s 安静模式,在输入字符时不再屏幕上显示,例如login时输入密码。

  • -t 后面跟秒数,定义输入字符的等待时间。

  • -u 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的。

 

 

从文件中读取(每次读一行)

    对文件使用cat命令,将结果通过管道直接传给含有read命令的while命令

#!/bin/bash

conut=1

cat file.conf | while read line2

do

echo "line #$count value $line2"

((count++))

done

 

ps:默认是以行分割,因为read 命令是换行读取

 

 

使用重定向输入读取文件

#!/bin/bash

# 重定向输入,读取文件

exec 0< file.conf

count=1

while read line

do

echo "Line #$count: $line"

count=$[ $count + 1 ]

done

 

 


重定向错误

 

 

错误的文件描述符 值是 2 

Linux的标准文件描述符

文件描述符  

缩写  

 

0

STDIN  

标准输入

1

STDOUT  

标准输出

2

STDERR  

标准错误

 

只重定向错误

#!/bin/baash

#将错误信息重定向到 文件

cat  new-6.sh 2> erro.log

echo "test command ehco" 2>> erro.log

 

[newcs@dsszbyz-etl-inf7 shell_test_dir]$ cat erro.log

cat: new-6.sh: No such file or directory

 

 

同时将重定向错误和正常输出

#!/bin/baash

ls shell_test_dir  bad  2>>shell_test_dir/erro.log 1>>shell_test_dir/info.log

ls shell_test_dir  bad  &>>shell_test_dir/debug.log

 

[newcs@dsszbyz-etl-inf7 shell_test_dir]$ cat debug.log

ls: cannot access bad: No such file or directory

shell_test_dir:

debug.log

erro.log

file.conf

info.log

new-2.sh

new-3.sh

new-4.sh

new-5.sh

 

 

"&>>" 、"&>"  将正确错误都重定向到同一个位置

 

永久重定向

exec  1> file

#!/bin/bash

#永久重定向

 

#exec 1>>info.log

exec &>>debug.log

echo `date  "+%Y-%m-%d %H:%M:%S"`

 

#exec 2>> error.log

ll ../shell_test_dir ../bad2

 

空文件/dev/null

  • 不显示存储输出            ls -al badfile test16 2> /dev/null

  • 删除文件内容               cat /dev/null > error.log

 

创建临时文件,并保存文件路劲、文件名

#!bin/bash

#创建临时文件

fileName=`mktemp test.XXX`           //mktemp命令会生成随机3个字符代替X(必须大写)

echo "temp file : `pwd`/$fileName "    //会建在当前目录下

 

#强制建在/tmp 中

fileName=`mktemp -t test.XXX`

echo "temp file : $fileName "        //   /tmp/test.wjy

 

 

同时重定向到文件和显示器

#!/bin/bash

#tee 命令 相当于T型管道,同时定向到文件和显示器

echo "test tee" | tee -a info.log

cat info.log | tee -a info.log

  •  -a 追加内容到文件末尾 , 没有 a 则执行覆盖操作

 


 

例:

读取csv文件,生成sql文件

#!bin/bash

# 读取csv文件,生成sql文件

outfile='demo1.sql'

IFE=','

 

while read param1 param2 param3

do

echo "insert into table values ($param1,$param2,$param3)" >> $outfile

#done < "file.csv"

done <$1

 


 

执行字符串中的命令

#!/bin/bash

#清理日志

command="cat /dev/null > error.log"

#command="ls"

echo "$command"

eval $command

 


 

常用时间格式化

date "+%Y-%m-%d %H:%M:%S"

 


控制shell

  • Ctrl+Z  停止当前shell中的任何进程,不是终止

Linux信号

信号

 

0

EXIT

结束退出

1

SIGHUP  

挂起进程

2

SIGINT  

终止进程

3

SIGQUIT  

停止进程

9

SIGKILL  

无条件终止进程

15

SIGTERM 

尽可能终止进程

17

SIGSTOP 

无条件停止进程,但不是终止进程

18

SIGTSTP  

停止或暂停进程,但不终止进程

19

SIGCONT

继续运行停止的进程

命令trap 捕捉对应的信号,将其截断,交由本地处理,而不是shell

 

例:

trap命令来忽略SIGINT(终止)信号

#!/bin/bash

# 捕捉trap,不让终止操作

echo "---start"

trap " echo 'can not stop'" 2       //将命令放到字符串中

count=0

for (( ; count<10; count++))

do

echo " #$count"

sleep 1

done

echo "---end"

 

trap "echo Goodbye..."  0        //shell 结束退出

 

 

[newcs@dsszbyz-etl-inf7 shell_test_dir]$ sh demo2.sh

---start

#0

#1

#2

#3

#4

^Ccan not stop

#5

^Ccan not stop

#6

^Ccan not stop

#7

#8

#9

---end

 

 

trap 的修改和移除

  • 修改      在需要修改的地方,新增就成

  • 移除      在需要移除的地方,加 trap --  【状态】   trap -- 2

 


 

后台运行

&    

在命令后加 "&"    sh test.sh &   但会将输出和错误信息都打印出来,和操作混合了,最好将脚本的STDOUT和STDERR重定向,同时退出终端时,会终止。

 

nohup

阻断所有发送给该进程的SIGHUP信号。即可在退出终端会话时阻止进程退出

自动将STDOUT和STDERR的消息重定向到一个名为nohup.out的文件中

 

指定nohup 输出

[newcs@dsszbyz-etl-inf7 shell_test_dir]$  nohup sh demo2.sh 1>info.log  2>error.log  &

 

 

作业控制:启动、停止、终止以及恢复作业的这些功能

$$ 当前脚本的PID 进程号

 


 

优先级

 

nice -n 10 ./test4.sh     nice -n 【级别】 【命令】   

renice -n 10 -p 5055    renice -n 【级别】 -p 【PID

 


 

函数

 

#!/bin/bash

 

格式一

function1() {

echo "trying to display a non-existent file"

ls -l badfile

 

# return 6    设置返回状态码(只能0~255)

}

 

格式二

function 【方法名】{

    【command

}

 

echo "testing the function: "

function1                                       //调用函数

echo "The exit status is: $?"                   //使用函数的结束状态码

 

让函数输出

 

#!/bin/bash

# 函数输出

f1(){

read -p "your age: " age

echo $age

}

 

age=`f1`

echo "you are $age old"

 

[newcs@dsszbyz-etl-inf7 shell_test_dir]$ sh 2-new.sh

your age: 2

you are 2 old

 

使用打印的方式,将函数值返回。

 

#!/bin/bash

# 函数输出

f2(){

param=("array1" "array2")

echo ${param[*]}

}

 

array=`f2`

echo "array : $array"                                    //输出array : array1 array2

echo "  ${arry[*]} |  ${array[0]}   |  ${array[1]} "     //输出   |  array1 array2   |

 

此种方法返回的是字符串,而不是数组

 

给函数传参数

#!bin/bash/

# 给函数传参数

 

f1(){

#echo $[ $1 - $2 ]        //参数只属于函数,和脚本的参数无直接关系

}

 

val=`f1 $1 $2`            //必须传命令行参数,否则会报错

echo "resualt= $val"

函数相当于小的shell脚本,可接受命令行参数,对参数的检验方法与脚本一致

 

在脚本主体运行函数时,没有使用命令替换(没有创建子shell),也可以。但无法传参数,无法返回值给变量。虽然脚本的任何参数都是全局,但得不偿失。

f1(){

echo "test"

}

 

#val=f1 $1 $2        //无法传值

f1

 

[newcs@dsszbyz-etl-inf7 shell_test_dir]$ sh 3-new.sh

test

 

 

函数接收、返回数组

#!/bin/bash/

# 函数接收、返回数组

 

f1(){

array1=(`echo $@`)

#l=" funci array1 : ${array[0]} | ${array[1]} | ${array[2]}"

#`echo $l`

 

array2=(1 2 3 4 5)

echo ${array2[*]}

}

 

array=(3 2 1)

array2=`f1 ${array[*]}`

echo "1_shell array2 : $array2"  //返回的是字符串

array3=(`echo ${array2[*]}`)     //符合数组的构造方法

echo "1_shell array : ${array[*]}"

echo "1_shell array3 : ${array3[0]} | ${array3[1]}  | ${array3[2]}"

 

 

[newcs@dsszbyz-etl-inf7 shell_test_dir]$ sh 5-new.sh

1_shell array2 : 1 2 3 4 5

1_shell array : 3 2 1

1_shell array3 : 1 | 2  | 3

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值