您的位置:首页 > 运维架构 > Shell

shell学习

2015-09-06 22:20 357 查看
Shell是用户与Linux操作系统沟通的桥梁

Linux的Shell种类众多,这里我们学习的是bash,也就是Bourne Again Shell,由于易用和免费,Bash在日常工作中被

广泛使用,同时,Bash也是大多数Linux系统默认的Shell。

文件名后缀通常是.sh

#!/bin/bash

#这里是注释

在一般情况下,人们并不区分 Bourne Shell和Bourne Again Shell,所以,在这里,我们可以看到#!/bin/bash,它同样

也可以改为#!/bin/sh。

shell单步调试:bash -x test.sh

shell语法检查:bash -n test.sh

变量

变量不需要声明,初始化不需要指定类型

变量命名

1:不能使用程序中的关键字(保留字)

2:只能使用数字,字母和下划线,且不能以数字开头

3:建议命令要通俗易懂

显示变量值使用echo命令 ,加上$变量名,也可以使用${变量名}

例如:echo $JAVA_HOME 或者 echo ${JAVA_HOME}

变量分类

本地变量:

只对当前shell进程有效的,对子进程和其它shell进程无效。

定义:VAR_NAME=VALUE 不能有空格

变量引用:${VAR_NAME}

取消变量:unset VAR_NAME

环境变量:

自定义的环境变量对当前shell进程及其子shell进程有效,对其它的shell进程无效

定义:export VAR_NAME=VALUE

对所有shell进程都有效需要配置到配置文件中

vi /etc/profile

source /etc/profile

局部变量:

函数调用结束,变量就会消失 对shell脚本中某代码片段有效

定义:local VAR_NAME=VALUE

位置变量:

$1,$2,.....${10}....

/tmp/test.sh a b

$0:脚本自身路径全名

$1:脚本的第一个参数

$2:脚本的第二个参数

特殊变量:

$?:接收上一条命令的返回状态码 如果执行成功,返回的状态码是0,执行失败的状态码在1-255之间 echo $?

$#:参数个数,可用于在脚本中用$#获取传入参数个数

$*:或者$@:所有的参数 ,可用于在脚本中用$*或$@获取传入的所有参数

$$:获取当前shell脚本的进程号,可以在脚本中使用$$获取当前脚本进程号

单引号、双引号、反引号

''单引号不解析变量

""双引号会解析变量

``反引号是执行并引用一个命令的执行结果,类似于$(...)

for循环

通过使用一个变量去遍历给定列表中的每个元素,在每次变量赋值时执行一次循环体,直至赋值完成所有元素退出循环

格式1

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

do

...

done

格式2

for i in 0 1 2 3 4 5 6 7 8 9

do

...

done

格式三

for i in {0..9}

do

...

done

条件测试

bash条件测试

命令执行成功与否即为条件测试

test EXPR

[ EXPR ]:注意中括号和表达式之间的空格

整型测试:

-gt:大于:例如[ $num1 -gt $num2 ]

-lt:小于

-ge:大于等于

-le:小于等于

-eq:等于

-nq:不等于

字符串测试:

>:大于[ "$str1" \> "$str2" ]

<:小于

=

!=

算术运算

let varNamer=算术表达式

varName=$[算术表达式]

varName=$((算术表达式))

varName=`expr $num1 + $num2`

while/until循环

适用于循环次数未知,或不便用for直接生成较大的列表时

格式:

while 测试条件

do

循环体

done

如果测试条件为“真”,则进入循环,退出条件为,测试条件为假。

until循环的格式和while循环的格式一致,但是和while循环的意思相反,如果测试条件为假,则进入循环,退出条件为,测试条件为真

if判断

单分支

if 测试条件;then

选择分支

fi

双分支

if 测试条件

then

选择分支1

else

选择分支2

fi

多分支

if 条件1; then

分支1

elif 条件2; then

分支2

elif 条件3; then

分支3

...

else

分支n

fi

例子:

if [ $1 -eq 1 ]

then

echo "one"

elif [ $1 -eq 2 ]

then

echo "two"

else

echo "none"

fi

case判断

有多个测试条件时,case语句会使得语法结构更清晰

格式: case 变量引用 in

PATTERN1)

分支1

;;

PATTERN2)

分支2

;;

...

*)

分支n

;;

esac

PATTERN :类同于文件名通配机制,但支持使用|表示或者

a|b:a或者b

*:匹配任意长度的任意字符

?:匹配任意单个字符

[]:指定范围内的任意单个字符

例子:

#!/bin/bash

case $1 in

1)

echo "one"

;;

2)

echo "two"

;;

3)

echo "three"

;;

*)

echo "none"

;;

esac

自定义函数

function 函数名(){

....

}

引用自定义函数文件时,使用source func.sh有利于代码的重用性

定义fun1.sh

#!/bin/bash

function test(){

echo "hello world"

}

定义fun2.sh直接调用test()函数

#!/bin/bash

source /usr/local/fun1.sh

test

date

显示当前时间

格式化输出

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

格式%s表示自1970-01-01 00:00:00以来的秒数

date +%s

指定时间输出

date --date='2009-01-01 11:11:11'

指定时间输出

date --date='3 days ago'

获取指定日期自1970-01-01 00:00:00以来的秒数

date --date='2009-01-01 11:11:11' +%s

read

read命令接收标准输入(键盘)的输入,或者其他文件描述符的输入。得到输入后,read命令将数据放入一个标准变

量中。

格式

read VAR_NAME

read -p "Enter your name:" VAR_NAME 有提示信息Enter your name:

read如果后面不指定变量,那么read命令会将接收到的数据放置在环境变量REPLY中

read -t 5 -p "enter your name:" VAR_NAME 倒计时5秒钟

read -s -p "Enter your password: " pass 秘密的输入,看不到输入的内容

declare

用来限定变量的属性

-r 只读

#!/bin/bash

num=0

echo $num 输出0

declare -r num

num=1

echo $num 输出0

-i 整数:某些算术计算允许在被声明为整数的变量中完成,而不需要特别使用expr或let来完成。

#!/bin/bash

declare -i num

let num=1+1

echo $num

-a 数组

字符串操作

获取长度:${#VAR_NAME}

name=zhangsan

echo ${#name} 输出8

字符串切片

name=zhangsan

${string:offset:length}

echo ${name:2:3} 输出ang

取尾部的指定个数的字符

name=zhangsan

${string: -length}:注意冒号后面有空格

echo ${name: -3} 输出san

取子串:基于模式

${variable#*word} 从左往右取第一个word后面的字符串

name=zhangsan

echo ${name#*a} 输出ngsan

${variable##*word} 从左往右截取第二个word后面的字符串

name=zhangsan

echo ${name##*a} 输出n

${variable%word*} 从右往左取第一个word后面的字符串

name=zhangsan

echo ${name%a*} 输出zhangs

${variable%%word*} 从右往左取第二个word后面的字符串

name=zhangsan

echo ${name%%a*} 输出zh

查找替换:

${variable/pattern/substr}替换第一次出现

${variable//pattern/substr}替换所有的出现

${variable/#pattern/substr}替换行首的pattern,如果行首没有此字符串,则不替换

${variable/%pattern/substr}替换行尾的pattern,如果行尾没有此字符串,则不替换

查找删除

${variable/pattern}删除第一次匹配的字串

${variable//pattern}删除所有匹配的字串

${variable/#pattern}删除行首匹配的字串

${variable/%pattern}删除行尾匹配的字串

大小写转换

小-->大:${variable^^}

大-->小:${variable,,}

变量赋值操作

${parameter:-word}

如果变量parameter的值为空或者不存在,返回结果为word,此时变量parameter的值依然为空

${parameter:=word}

如果变量parameter的值为空或者不存在,返回结果为word,此时将word赋值给变量parameter

${parameter:?word}

如果变量parameter的值为空或者不存在,则把word当作错误信息返回。

${parameter:+word}

如果变量parameter的值存在,返回结果为word。如果变量不存在,则返回为空。

数组

定义:declare -a:表示定义普通数组

特点

支持稀疏格式

仅支持一维数组

数组赋值方式

一次对一个元素赋值a[0]=$RANDOM

一次对全部元素赋值a=(a b c d)

按索引进行赋值a=([0]=a [3]=b [1]=c)

命令替换 logs=($(ls /var/log/*.log)) 将/var/log/下所有的.log文件名作为数组元素存储在logs数组中

使用read命令read -a ARRAY_NAME

获取数组的长度

${#ARRAY[*]}

${#ARRAY[@]}

注意:${#ARRAY}表示获取数组中的第一个元素的长度,等于${#ARRAY[0]},等于$ARRAY

从数组中获取某一片段之内的元素

格式: ${ARRAY[@]:offset:number}

offset:偏移的元素个数

number:取出的元素的个数

${ARRAY[@]:offset}:取出偏移量后的所有元素

${ARRAY[@]}:取出数组中的所有元素

数组复制:(建议使用${ARRAY[@]})

$@:每个参数都是一个独立的串

$*:所有参数是一个串

删除元素:

unset ARRAY[index]

脚本后台运行,执行

sleep.sh & 但是如果关闭终端就会退出。因为终端关闭时终端会发送hangup命令停止该终端的所有进程

可以使用:nohup sleep.sh & 这样即使关闭终端脚本仍然继续执行着,输出日志可查看当前路径的nohup.out

标准输入、输出、错误

标准输入、输出、错误都是命令行,使用文件描述符0、1、2引用

cat > catfile < ~/.bashrc

ls >file 或者 ls 1>file 这样把每次的输出都会覆盖进file,如果想追加在原内容后面可以使用ls >> file

lk 2>file(lk是一个错误命令)

使用重定向可以把信息转换到其他位置

ls folder 2> /dev/null 将错误信息扔进黑洞

ls folder 1>/dev/null 2>&1 将正确信息和错误信息全扔掉

crontab定时器

使用crontab -e 添加定时任务

* * * * * echo 'date' >> /usr/local/date.log

每分钟输出时间信息,里面指定的文件或脚本必须是全路径

* * * * * echo 'date' >> /usr/local/shell.sh

每分钟执行shell.sh脚本,必须是全路径

可以使用tail -f /usr/local/date.log监控输出结果

crontab定时任务可以执行的前提是必须启动cron服务:service crond start。查看状态:service crowd status

ps用来显示当前shell启动的进程相关信息

ps -e 显示系统中所有进程

ps -ef | grep bash
jps显示所有java进程,但是有时候查看不到,可以使用ps -ef|grep java查看

在编写批量执行脚本,需要ssh到远程服务器执行的脚本时,由于ssh到远程服务器时,不会主动加载/etc/profile只会

加载~/.bashrc或/tmp/bashrc,所以需要将source /etc/profile命令添加到bashrc脚本中,批量脚本才能正确加载到远

程服务器的环境变量,脚本才能正确执行。

vi小技巧

非编辑模式下:

查找字符串:/string 找到后按n找下一个

按:输入数字,跳到指定行

复制一行:光标移到该行任意位置,按两下yy,复制完毕。再按p粘贴。要复制两行先按2,光标移到第一行按yy。

跳到最后一行:大写g
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: