这段时间工作中需要写些Spark大数据脚本,用到了Shell脚本,基本都是靠抄前人的代码,就是替换一下SQL,写完了有时候也有点懵🤔️。好久之前就想好好学一下sh脚本,一直没有时间💦,这次要认真学完💪
第一个shell脚本 1 2 3 4 5 6 7 8 #!/bin/bash :<< EOF 注释1 注释2 EOF echo "Hello world!"
添加执行权限:chmod +x start.sh 后执行脚本:./start.sh
shell变量 变量定义和操作
字母A-Z ➕ 数字🔢 ➕ 下划线_
不能以数字开头、不能包含bash关键字⚠️
1 2 username="Bob" echo "username is \"${username} \""
单引号字符串会原样输出,双引号可以转义字符、读取变量
1 2 3 4 5 6 7 #!/bin/bash readonly TEN=10username="Bob" echo "username的值为:\"${username} \"" echo "TEN is ${TEN} "
字符串操作
1 2 username="John" echo "length is ${#username} "
1 echo "substring 1-4: ${username:1:2} "
shell数组 数组定义 shell不支持多维数组,各数组元素用空格🈳️隔开,下标范围没有限制。
1 2 names=("user1" "user2" "user3" ) names[4]="user4"
读取数组元素 1 2 3 4 5 user1=${users[0]} echo "${users[@]} "
数组长度 1 2 3 4 5 6 7 8 9 10 11 echo "array length is ${#users[@]} " echo "array length is ${#users[*]} " echo "elem length is ${#users[0]} " for element in ${users[*]} ; do echo "user is: ${element} " done
注释 1、单行注释
2、多行注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 :<<EOF 第一行注释 第二行注释 ... EOF :<<! 第一行注释 第二行注释 ... ! :<<' 第一行注释 第二行注释 ... '
shell传递参数 $1为第一个参数、$2为第二个参数….
特殊含义的参数:
参数名称
参数含义
$#
传递的参数的个数
$*
显示所有的参数(字符串形式
$$
显示当前脚本运行的进程号
$?
最后脚本退出的状态,0表示没有错误,其他表示有错误
运算符 1 2 3 val=`expr 2 + 2` val=`$1 == $2 `
echo
大学的时候,有个老乡学姐的QQ昵称就是Echo这几个字母,然后去查了下是“回音”的意思。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 echo "Hello world!" echo Hello world!echo "\"Hello world!\"" echo "value of param is ${param} " echo "file content" > fileecho `date `
printf格式化输出 1 2 3 4 5 printf "%d只乌龟🐢%d条%s\n" 1 4 '腿🦵' printf "%-10s%-10s%-10s\n" "标题1" "标题2" "标题3" printf "%-10s%-10s%-10s\n" "值1" "值2" "值3"
test命令 数值比较 Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
参数
说明
-eq
是否相等
-ne
是否不相等
-gt
是否大于
-lt
是否小于
-le
是否小于等于
-ge
是否大于等于
字符串比较
参数
说明
=
是否相等
!=
是否不相等
-z 字符串
字符串长度是否为0
-n 字符串
字符串长度是否不为0
文件比较
参数
说明
-e 文件名
如果文件存在则为真
-r 文件名
如果文件存在且可读则为真
-w 文件名
如果文件存在且可写则为真
-x 文件名
如果文件存在且可执行则为真
-s 文件名
如果文件存在且至少有一个字符则为真
-d 文件名
如果文件存在且为目录则为真
-f 文件名
如果文件存在且为普通文件则为真
-c 文件名
如果文件存在且为字符型特殊文件则为真
-b 文件名
如果文件存在且为块特殊文件则为真
与 或 非
猜数小游戏
$[$RANDOM % 100] 产生0-100之间的随机数
read -p “placeholer” param 将用户输入存入 param 变量中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 :<<! 前段时间组里团建,吃饭的时候和领导一桌, 吃饭后气氛有点尴尬😅,领导搞了个游戏, 每次由某个人准备一个数字并保密,然后大家依次轮流猜, 准备数字的人告知此次猜数是大了还是小了,只能在每次缩小的范围中选数, 最后猜中的人要接受惩罚。 学完shell脚本变量、注释、数组、参数传递、随机数、输出、if 判断后写的猜数小游戏! ! input_num=0 random_num=0 flag="" echo "欢迎来猜猜看!" while true do read -p "开始游戏?> " flag if test ${flag} = "Y" then random_num=$[$RANDOM % 100] while test ${input_num} -ne ${random_num} do read -p "请输入数字 > " input_num if test ${input_num} -gt ${random_num} then echo "大了" else echo "小了" fi done echo "恭喜!猜对了🎉" else echo "退出游戏.." kill $$ fi done
流程控制 if-elif-else 语法:
1 2 3 4 5 if conditionthen command1 command2 fi
1 2 3 4 5 6 7 8 9 10 if conditionthen command1 command2 elif condition2then command3 else command4 fi
例子🌰:
1 2 3 4 5 6 7 8 9 10 11 12 #!/bin/bash age=35 std=30 if [ ${age} -gt ${std} ]; then echo "年龄合格🈴️" elif [ ${age} -eq ${std} ]; then echo "巧了㊗️" else echo "无缘👋" fi
for 语法:
1 2 3 4 5 for item in val1 val2 val3do command1 command2 done
例子🌰
1 2 3 4 5 6 7 8 #!/bin/bash sum =0for item in 1 2 3 6do ((sum=sum+item)) done echo "sum is ${sum} "
while 语法:
1 2 3 4 while conditiondo command done
case-esca 语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 case ${val} in case1) command1 command2 ;; case2) command3 commmad4 ;; *) command5 command6 ;; esac
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #!/bin/bash read -p "input: " valcase ${val} in "a" ) echo "input a" ;; "b" ) echo "input b" ;; *) echo "input other" ;; esac
函数
linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
语法:
1 2 3 function fun_name () { command }
函数的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #!/bin/bash function test1 () { echo "running test1." echo "param1 is $1 " echo "param2 is $2 " } echo "start call test1()" test1 p1 p2 p3 echo "end call test1()" start call test1() running test1. param1 is p1 param2 is p2 end call test1()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/bin/bash function add_two_num () { echo "请输入第一个数字" read num1 echo "请输入第二个数字" read num2 echo "输入的两个数字分别为:${num1} ${num2} " return $((${num1} + ${num2} )) } echo "对输入的两个数字求和" add_two_num echo "和为:$?"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #!/bin/bash function find_max () { local val1=$1 local val2=$2 local val3=$3 local temp=0 if [ ${val1} -ge ${val2} ] then temp=${val1} else temp=${val2} fi if [ ${temp} -ge ${val3} ] then return ${temp} else return ${val3} fi } find_max 3 1 6 echo "max value is $?"
文件包含 两种方式:. filename 或者 source filename
1 2 3 4 5 URL_BAIDU="https://www.baidu.com"
1 2 3 4 5 6 7 8 #!/bin/bash source ./url.shecho "导入的url为:${URL_BAIDU} "
shell输入输出重定向 输入输出重定向
命令
说明
command > file
将输出重定向到file
command < file
将输入重定向到file
commad >> file
将输出以追加的方式重定向到file
n >& m
将输出文件m和n合并
n <& m
将输入文件m和n合并
<< tag
将开始标记 tag 和结束标记 tag 之间的内容作为输入
1 2 3 echo "Hello world!" > tmp.txtwc -l < tmp.txt
如果希望 stderr 重定向到 file,可以这样写:
如果希望 stderr 追加到 file 文件末尾,可以这样写:
2 表示标准错误文件(stderr)。
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
1 2 3 4 5 $ command > file 2>&1 或者 $ command >> file 2>&1
如果希望对 stdin 和 stdout 都重定向,可以这样写:
1 $ command < file1 > file2
command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
命令
说明
stdin(文件描述0
标准输入
stdout(文件描述符1
标准输出
stderr(文件描述符2
标准错误
Here document Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
1 2 3 command << delimiter document delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
开始的delimiter前后的空格会被忽略掉。
1 2 3 4 5 6 7 8 wc -l << EOF 欢迎来到 菜鸟教程 www.runoob.com EOF 3
/dev/null 文件 如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出”的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
1 $ command > /dev/null 2>&1
这里的 2 和 > *之间不可以有空格,*2> 是一体的时候才表示错误输出。