有无export的区别:
无export 对当前父shell有效,shell无效
有export 对当前窗口有效
shell变量知识进阶与实践
1)直接赋值
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#变量直接赋值
a=1
b=2
echo $a $b
[root@web01 script]#
2)传参赋值
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#传参赋值
a=$1
b=$2
echo $a $b
[root@web01 script]# sh test.sh 红烧肉 西红柿炒鸡蛋
红烧肉 西红柿炒鸡蛋
3)交互式赋值
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#交互式赋值
read -p "请输入一个学员名字:" name(变量)
echo $name(调用变量)
[root@web01 script]# sh test.sh
请输入一个学员名字:lsy
lsy
[root@web01 script]#
企业使用:可以根据需求调整变量,可以便于新员工快速掌握脚本的使用
read命令 -p 参数解释: 阅读命令从标准输入中读取一行,并且把输入行的每个分区的值指定给shell变量
-p 后面跟提示信息,在输入前打印提示信息
脚本中特殊变量说明:
01 位置变量作用说明
1 $0 获得脚本名称信息;直接显示脚本名称,或包含脚本的绝对路径
实际应用
2 $n 脚本的第n个参数 ,n表示从1..9 (不能到10),大于9的数量用${10}组合起来
实际应用:识别脚本后面参数信息
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#$n 特殊变量使用方法
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
[root@web01 script]# sh test.sh 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
3 $# 代表脚本的传参总数信息, 多个传参参数以空格进行分割, 可以用双引号将多个空格分割参数汇总为一个整体 4 $* 输出脚本的所有参数;加上引号信息时,和$@不同,加上引号是看成一个整体 5 $@ 输出脚本的所有参数;加上或者不加引号;都表示将多个参信息看成独立的个体
$0 获得脚本名称信息;直接显示脚本名称
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#显示脚本名称的特殊变量$0
echo $0
[root@web01 script]# sh test.sh
test.sh
[root@web01 script]# sh /server/script/test.sh
/server/script/test.sh
[root@web01 script]#
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#显示脚本名称的特殊变量$0
echo Usage: $0 {请输入学生姓名和年龄}
echo "请输入学生姓名:$1"
echo "请输入学生年龄:$2"
[root@web01 script]# sh test.sh 张三 30
Usage: test.sh {请输入学生姓名和年龄}
请输入学生姓名:张三
请输入学生年龄:30
[root@web01 script]#
扩展:
01 如何获得一个文件所在路径信息:
02 如何只显示一个文件的名称信息:
[root@web01 script]# echo /oldboy/oldboy01/oldboy03/oldboy.txt
/oldboy/oldboy01/oldboy03/oldboy.txt
[root@web01 script]# echo /oldboy/oldboy01/oldboy03/oldboy.txt |xargs dirname
/oldboy/oldboy01/oldboy03
[root@web01 script]# echo /oldboy/oldboy01/oldboy03/oldboy.txt |xargs basename
oldboy.txt
[root@web01 script]#
dirname 显示指定路径出了文件名之外的路径前缀
basename 去掉前面的路径,只显示文件名称
$n 脚本的第n个参数
补充:生成序列信息的特殊方法
[root@web01 script]# echo \${1..9}
$1 $2 $3 $4 $5 $6 $7 $8 $9
[root@web01 script]#
方法二:sep -s (指定分割符–默认是回车为分隔符) 但是第一个有点问题,也就是1在开头,没法执行
[root@web01 script]# seq -s " $" 20
1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 $19 $20
$# 代表脚本的传参总数信息, 多个传参参数以空格进行分割, 可以用双引号将多个空格分割参数汇总为一个整体
脚本应用:
[ $# -eq 2 ] || echo "Usage: $0 {请写入学生年龄和姓名}"
$*
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#$@ $* 特殊变量使用方法
echo $1 $2 $3
echo $@
echo $*
[root@web01 script]# sh test.sh oldboy oldgirl oldgod lsy 1 2 3 4 5 6 7 8
oldboy oldgirl oldgod
oldboy oldgirl oldgod lsy 1 2 3 4 5 6 7 8
oldboy oldgirl oldgod lsy 1 2 3 4 5 6 7 8
$* 和 $@的区别
演示说明
准备参数变量信息
set – “i an oldboy teacher”
[root@web01 script]# set -- “i an oldboy teacher”
[root@web01 script]# echo $#
4
[root@web01 script]# echo $1
“i
[root@web01 script]# echo $2
an
[root@web01 script]# echo $3
oldboy
[root@web01 script]# echo $4
teacher”
测试$* 和 $@之间的区别 ,不加双引号信息没有任何区别
[root@web01 script]# echo $*
“i an oldboy teacher”
[root@web01 script]# echo $@
“i an oldboy teacher”
[root@web01 script]#
说明:不加双引号,两者没有任何区别
区别体现在循环体结构中
测试$@ $* 之间的区别 加上引号信息
[root@web01 script]# echo "$@"
“i an oldboy teacher”
[root@web01 script]# echo "$*"
“i an oldboy teacher”
[root@web01 script]#
在循环体中,不加双引号
[root@web01 script]# for i in $@; do echo $i ;done
i
an
oldboy
teacher
[root@web01 script]# for i in $*; do echo $i ;done
i
an
oldboy
teacher
没有什么区别
在循环体中,加双引号(环境准备时set – “i am” oldboy teacher)
[root@web01 script]# for i in "$*"; do echo $i ;done
i an oldboy teacher
说明:将$*识别所有参数汇总成一个整体参数 赋值给循环体中变量i
[root@web01 script]# for i in "$@"; do echo $i ;done
i an
oldboy
teacher
[root@web01 script]#
说明:将$@是别所有参数单独进行识别,赋值给循环体中变量i
但是参数设置有双引号,就会是别成响应的一个整体
总结:加上双引号,在循环体中 $* 会将所有参数看成一个整体 $@ 会将所有参数看成多个个体
什么需求 需要用到"$*" 把传参看成一个整体
#分析日志信息
#2020-4-1 error 订单出现异常
#01: 统计有多少个错误订单 错误出现日期 定订单情况
#$* date=2020-4-1 log_status=error info=订单出现异常 echo $date $订单情况
#02: 将日志中出现错误日志整体显示输出
#"$*" error_info=2020-4-1 error 订单出现异常
02 状态变量作用说明:
1 $? 获取上一个执行结果 成功用0表示 失败用非0表示
2 $$ 获取当前pid信息
3 $! 获取上一个程序或脚本后台运行的pid信息
4 $_ 获取脚本的最后一个参数信息
1 $? 获取上一个执行结果 成功用0表示 失败用非0表示
实际应用:判断命令是否执行成功
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#$? 判断命令是否成功与否
[ $# -ne 1 ] && echo $0 "{请输入一个域名地址:}" && exit 2
ping -c 2 $1 >/dev/null 2>1
[ $? -eq 0 ] && echo "this web_name $1 is ok." ||echo "this is web_name $1 is error"
[root@web01 script]#
3 $! 获取上一个程序或脚本后台运行的pid信息 守护进程方式执行脚本(sh test04.sh &)
[root@web01 script]# cat test.sh
#!/bin/bash
#lsy output info
#$? 判断命令是否成功与否 普通进程
[ $# -ne 1 ] && echo $0 "{请输入一个域名地址:}" && exit 2
while true
do
ping -c 2 $1 >/dev/null 2>1
[ $? -eq 0 ] && echo "this web_name $1 is ok." >>/tmp/test_ping.txt ||echo "this is web_name $1 is error" >>/tmp/test_ping.txt
sleep 10
done
#echo $$ >/tmp/test.pid
有些进程是出现又消失的
有些进程是一直存在的(守护进程)
3)脚本中变量子串说明
${paramter} 返回变量信息内容,将变量内容做解析
实际应用:识别子串变量信息
企业面试题
企业面试题目:
已知一个变量 OLDBOY=“I am oldboy teacher”, 问变量信息字符数量是多少, 如何统计
方法一:
echo $OLDBOY|wc -L
测试响应效率:
time for n in {1..10000};do char=`seq -s "oldboy" 100`;echo ${char}|wc -L &>/dev/null;done
方法二:
expr length "$OLDBOY"
测试响应效率:
time for n in {1..10000};do char=`seq -s "oldboy" 100`;expr length "${char}" &>/dev/null;done
方法三: 效率最低
echo $OLDBOY|awk '{print length}'
测试响应效率:
time for n in {1..10000};do char=`seq -s "oldboy" 100`;echo "${char}"|awk '{print length($0)}' &>/dev/null;done
企业面试题目:
已知一个变量 OLDBOY="I am oldboy teacher my name is HQ"
请找出字符串长度小于3的信息
方法一:
for i in I am oldboy teacher my name is HQ
do
[ ${#i} -lt 3 ] && echo $i
done
方法二:
# echo $OLDBOY|xargs -n1|awk '{if(length<3)print}'
I
am
my
is
HQ
方法三:
# echo $OLDBOY|awk '{for(i=1;i<=NF;i++)if(length($i)<3)print $i}'
I
am
my
is
HQ
方法四:
echo $OLDBOY|egrep -wo "[a-Z]{1,3}"
补充: 识别KaTeX parse error: Expected 'EOF', got '#' at position 45: …ripts 14:52:55]#̲ echo "{oldboy}isok"
linuxisok
[root@web01 scripts 14:53:11]# echo ‘${oldboy}isok’
${oldboy}isok
总结: $字符串 $数字 $符号 ${} --- 避免金庸新著 $() == `` 将引号里面信息命令进行执行
${#paramter}
返回变量内容字符长度.
# OLDBOY=“I am oldboy teacher”
# echo ${#OLDBOY}
19
测试响应效率: 效率最高
time for n in {1..10000};do char=`seq -s "oldboy" 100`;echo ${#char} &>/dev/null;done
real 0m19.808s
user 0m6.019s
sys 0m13.647s
${paramter:offset}
在变量中,从指定字符位置开始提取子串到结尾的信息
${paramter:offset:length}
在变量中,从指定字符位置开始提取子串到指定位置结束
补充:子串中offset信息可以从0开始
[root@web01 script]# echo ${OLDBOY::4}
I am
[root@web01 script]# echo ${OLDBOY:0:4}
I am
[root@web01 script]#
${paramter#word}
从变量开头开始删除最短匹配的word子串信息;留下没匹配的(默认匹配一次)
[root@web01 script]# OLDBOY=abcABC123ABCabc --匹配到了abc 所以开头的abc没有显示
[root@web01 script]# echo $OLDBOY
abcABC123ABCabc
[root@web01 script]# echo ${OLDBOY#a*c}
ABC123ABCabc
[root@web01 script]#
从变量开头开始删除最长匹配的wword子串信息。
[root@web01 script]# OLDBOY=abcABC123ABCabc
[root@web01 script]# echo $OLDBOY
abcABC123ABCabc
[root@web01 script]# echo ${OLDBOY##a*C}
abc
${oarameter%word}
[root@web01 script]# echo ${OLDBOY%a*c}
abcABC123ABC
${parameter%%word}
[root@web01 script]# echo ${OLDBOY%%a*c}
[root@web01 script]# echo $OLDBOY
abcABC123ABCabc
[root@web01 script]# echo ${OLDBOY%%C*c}
abcAB
${parameter/string/replace}
使用repliace 信息替换string字符串,并且只替换第一个匹配的信息
[root@web01 script]# OLDBOY="I am oldboy teacher,I am oldboy linux teacher"
[root@web01 script]# echo $OLDBOY
I am oldboy teacher,I am oldboy linux teacher
[root@web01 script]# echo ${OLDBOY/oldboy/oldgirl}
I am oldgirl teacher,I am oldboy linux teacher
[root@web01 script]#
${parameter//string/replace}
使用replace信息替换string字符串信息,但是会将所有信息替换
[root@web01 script]# echo ${OLDBOY/oldboy/oldgirl}
I am oldgirl teacher,I am oldboy linux teacher
[root@web01 script]# echo ${OLDBOY//oldboy/oldgirl}
I am oldgirl teacher,I am oldgirl linux teacher
一个/是替换第一个匹配的
两个//是替换所有匹配的信息
${paramter} 返回变量信息内容,将变量内容做解析
实际应用:识别子串变量信息
[root@web01 script]# oldboy=linux
[root@web01 script]# echo $oldboy
linux
[root@web01 script]# echo ${oldboy}
linux
[root@web01 script]# echo ${oldboy}idok
linuxidok
[root@web01 script]# echo ${oldboy}isok
linuxisok
[root@web01 script]# echo $oldboyisok
[root@web01 script]#
双引号 可以识别变量 ;单引号所见即所得,无法解析变量
[root@web01 script]# echo "${oldboy}isok"
linuxisok
[root@web01 script]# echo '${oldboy}isok'
${oldboy}isok
[root@web01 script]#
表示运算 $[]
[root@web01 script]# echo $[1+4]
5
[root@web01 script]# time for n in {1..10000};do char=`seq -s "oldboy" 100` ;echo ${#char} &>/dev/null ; done
real 0m16.820s
user 0m6.243s 用户态
sys 0m10.491s 内核态
[root@web01 script]#
如何利用替换子串信息,批量修改文件名称
准备环境:
[root@web01 oldboy]# ll
total 0
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_01_linux.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_02_linux.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_03_linux.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_04_linux.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_05_linux.txt
[root@web01 oldboy]#
[root@web01 oldboy]# for i in `ls |xargs -n1` ;do mv $i ${i/_linux} ;done
[root@web01 oldboy]#
[root@web01 oldboy]# ll
total 0
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_01.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_02.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_03.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_04.txt
-rw-r--r-- 1 root root 0 Apr 1 04:39 oldboy_2020_05.txt
4)脚本中变量替换说明
${parameter:-word}
当调取变量信息的值为空时或者未赋值,就返回word字符信息
作用说明:如果变量未定义,则返回备用字符串信息,防止变量为空值或者未定义导致异常
${parameter:=word}
作用说明:如果变量未定义,则设置指定字符串为
[root@web01 oldboy]# lead=孙俪
[root@web01 oldboy]# echo $lead
孙俪
[root@web01 oldboy]# unset lead
[root@web01 oldboy]# echo $lead
[root@web01 oldboy]# echo ${lead:-替演}
替演
[root@web01 oldboy]# echo ${lead:=周迅}
周迅
[root@web01 oldboy]# echo $lead
周迅
[root@web01 oldboy]
说明:如果变量未定义,用指定字符串直接给变量赋值
${parameter:?word}
当调取变量信息的值为空时或者未赋值,错误提示信息word
[root@web01 oldboy]# echo $OLDBOY
[root@web01 oldboy]# echo ${OLDBOY:?此变量未进行赋值设置}
-bash: OLDBOY: 此变量未进行赋值设置
[root@web01 oldboy]#
${parameter:+word}
当调取变量信息值为空时或者未赋值,不做任何处理,否则word字符串将替代变量值
[root@web01 oldboy]# oldboy=${oldgirl:+linux69}
[root@web01 oldboy]# echo $oldboy
[root@web01 oldboy]# oldgirl=python
[root@web01 oldboy]# oldboy=${oldgirl:+linux69}
[root@web01 oldboy]# echo $oldboy
linux69
[root@web01 oldboy]#
总结:
如果变量未定义,调取变量信息时,不会有任何显示
如果变量已经定义,调取变量信息时,会显示指定字符串信息
?word: 变量未定义提示错误信息; 变量已定义显示变量信息
+word: 变量未定义不做任何处理; 变量已定义显示提示信息