变量5种赋值方式
shell中变量赋值5种方式,其中采用name=10的方法称A 直接赋值 name=B read命令 read v1C 使用命令行参数 ($1 $2 $3 ..) name=$1D 使用命令的输入 username=$(whoami)E 从文件读取 #cut -d : -f1 /etc/passwd > /user.listfor user in $(cat /user.list);doecho $userdonewhile read user;doecho $userdone < user.list
变量和引号
Shell语言中一共有3种引号,分别为
- 单引号(' ')单引号括起来的字符都作为普通字符出现
- 双引号(" ")双引号括起来的字符,除“$”、“\”、“'”和“"”这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待,
- 反引号(``)反引号括起来的字串被Shell解释为命令,在执行时,Shell首先执行该命令,并以它的标准输出结果取代整个反引号(包括两个反引号)部分
符号 | 说明 |
---|---|
双引号 | 除美元符号、单引号、反引号和反斜线之外,其他所有的字符都将保持字面意义 |
单引号 | 所有的字符都将保持字面意义 |
反引号 | 反引号中的字符串将被解释为Shell命令 |
反斜线 | 转义字符,屏蔽后的字符的特殊意义 |
演示:引号的区别
[root@localhost ~]# echo "current_user is: $USER"
current_user is: root
[root@localhost ~]# echo 'current_user is: $USER'
current_user is: $USER
[root@localhost ~]# echo "current_user is: `whoami`"
current_user is: root
[root@localhost ~]# echo 'current_user is: `whoami`'
current_user is: `whoami`
变量的运算
运算符与命令
-
例:
r=$((2+5*8)) ---需要通过$引用运算值---- (()) 可以直接运算 运算结果需要通过变量接受
((dec=num-1))
r=$[1+2] $[] 不能直接运算 运算结果需要通过变量接受
declare –i r=2+3 申明整形变量对数值进行运算
let r=3+4 let 可以直接运算 运算结果需要通过变量接受
expr 4 + 2 后三种可以直接运算输出运算结果
expr 也可用字符串expr length “this is a test”expr substr "this is a test" 3 5 从第三个字符开始取5个字符expr index "sarasare" a 抓取指定字符第一次出现的位置,标记第一个a字符是第2个字符
r=`expr 4 + 2`
bc
echo "2+5*8" | bc
awk 'BEGIN {print 2+5*8}'
[root@server ~]# expr 1 + 1 # 注意+左右必须要有空格
2
[root@server ~]# expr 1+1 # 否则原样显示
1+1
[root@server ~]# a=1
[root@server ~]# b=2
[root@server ~]# expr $a + $b # 支持变量
3[root@server ~]# let num=1+2 # let+echo 等价于expr
[root@server ~]# echo $num
3
[root@server ~]# let num=1 + 2 # 注意let中运算符左右不能由空格
-bash: let: +:语法错误: 需要操作数 (错误符号是 "+")[root@server ~]# echo $((1+2))
3
[root@server ~]# echo $((5%3))
2
[root@server ~]# echo $((3%5))
3
[root@server ~]# echo $((1-5))
-4
[root@server ~]# echo $((2 * 5)) # 可以有空格
10
[root@server ~]# echo $((5.2-5)) # 只支持整数运算
-bash: 5.2-5:语法错误: 无效的算术运算符 (错误符号是 ".2-5")[root@server ~]# echo $[2+3] # [] 等价于 (())
5
[root@server ~]# echo $[2.5+3] # # 只支持整数运算
-bash: 2.5+3:语法错误: 无效的算术运算符 (错误符号是 ".5+3")
[root@server ~]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software
Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1.1+2
3.1
2.5-3.9
-1.4
1.5>4
0
5>3
1
quit # 退出交互模式
# 不进入交互模式直接使用,bc需要放在最后
[root@server ~]# echo "scale=3;11/3" | bc
3.666
# scale=3 表示保留运算精度
-
例2:计算用户输入的任意两个整数的和、差、乘积、商、余数
# 方法1
[root@server ~]# cat 1.sh
#!/bin/bash
a=$1
b=$2
echo a+b=$(($a+$b))
echo a-b=$((a-b))
echo a*b=$((a*b))
echo a/b=$((a/b))
echo a%b=$((a%b))
[root@server ~]# ./1.sh 10 3
a+b=13
a-b=7
a*b=30
a/b=3
a%b=1
# 方法2:
[root@server ~]# cat 1.1.sh
#!/bin/bash
read -p "please input two number:" a b
echo $a+$b=$(($a+$b))
echo $a-$b=$((a-b))
echo $a*$b=$((a*b))
echo $a/$b=$((a/b))
echo $a%$b=$((a%b))
[root@server ~]# ./1.1.sh
please input two number:3 4
3+4=7
3-4=-1
3*4=12
3/4=0
3%4=3
-
例3:计算 1~ 100 的和
# 方法1:
[root@server ~]# cat 2.sh
#!/bin/bash
# 1. 使用 echo {1..100} 生成 1 到 100 字符串
# 2. 然后使用 tr 命令来将空格替换为 + 号 echo {1..100} | tr " " "+"
# 3. 使用管道加bc命令来实现
echo {1..100} | tr " " "+" | bc
# 方法2:
root@server ~]# cat 2.1.sh
#!/bin/bash
# 使用 seq 命令来实现 seq -s "+" 100,然后接合双括号来实现
echo $((`seq -s "+" 100`))
# 方法3:
[root@openEuler ~]# cat 2.2.sh
#!/bin/bash
# 使用 expr 命令来实现
seq -s " + " 100 | xargs expr
-
例3:6种方式计算长方形的面积
s1=$(( $l * $w ))
echo "1--面积是$s1"---'$(())'let s2=$l*$w
#let s2=l*w
echo "2--面积是$s2"---'let's3=`expr $l \* $w`
echo "3--面积是$s3"---'expr’'s4=`echo "$l * $w" | bc`
echo "4--面积是$s4"---'bc's5=$[ $l * $w ]
#s5=$[ l * w ] #可以有空格
echo "5--面积是$s5"---'$[]'declare -i s6=$l*$w #不能有空格
#declare -i s6=l*w
echo "6--面积是$s6"---'declare'
字符运算
格式
表达式 | 说明 |
---|---|
${parameter} | 返回变量的内容 |
${#parameter} | 返回变量内容的长度(按字符) |
${paramater:offset} | 在变量${parameter}中,从位置offset之后开始提取子串到结尾 |
${paramater:offset:length} | 在变量${parameter}中,从位置offset之后开始提取长度为length的子串 |
${parameter#word} | 从变量${parameter}开头开始删除最短匹配的word子串 |
${parameter##word} | 从变量${parameter}开头开始删除最长匹配的word子串 |
${parameter%word} | 从变量${parameter}结尾开始删除最短匹配的word子串 |
${parameter%%word} | 从变量${parameter}结尾开始删除最长匹配的word子串 |
${parameter/pattern/string} | 使用string代替第一个匹配的pattern |
${parameter//pattern/string} | 使用string代替所有匹配的pattern |
获取字符串
${parameter} 返回变量的内容
${#parameter} 返回变量内容的长度(按字符)
[root@server ~]# str="hello world"
#返回变量长度
[root@server ~]# echo ${#str}
11
截取字符串
${paramater:offset} 在变量${parameter}中,从位置offset之后开始提取子串到结尾
${paramater:offset:length} 在变量${parameter}中,从位置offset之后开始提取长度为length的子串
[root@server ~]# echo ${str1:0:3} # 从左边第1个字符开始截取3个
hel
[root@server ~]# echo ${str1::3} # 可以省略起始0
hel
[root@server ~]# echo ${str1:1} # 从下标1开始截取到尾部
ello world
[root@server ~]# echo ${str1:0-1:1} # 从右边第一个字符开始截取1个,左边第一个为0,右边第一个为0-1
d
[root@server ~]# echo ${str1:0-5} # 从右边第5个开始截取到尾部
world
[root@server ~]# echo ${str1: -5} # 使用空格替代0,同上
world
注意:下面写法会输出全部,以${parameter:-default}方式,默认是提取完整地字符串
[root@server ~]# echo ${str1:-5} # 没有空格表示提取整串
hello world
删除字符串
${parameter#word} 从变量${parameter}开头开始删除最短匹配的word子串
${parameter##word} 从变量${parameter}开头开始删除最长匹配的word子串
${parameter%word} 从变量${parameter}结尾开始删除最短匹配的word子串
${parameter%%word} 从变量${parameter}结尾开始删除最长匹配的word子串
# 使用%截取,删除右边字符,保留左边字符
[root@server ~]# filename=testfile.tar
[root@server ~]# file=${filename%.*} # %.表示从右边开始检索第一次出现. 之后删除.右侧的内容,#保留左边内容,用于对文件名去掉扩展名
[root@server ~]# echo $file
testfile
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url%%:*} # %%: 表示从右边开始检索最后一次出现的: #之后删除:右侧的内容,保留左边内容
[root@server ~]# echo $ul1
http
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url#*.} # #*.表示左向右遍历,删除第一次出现的.左侧内容
[root@server ~]# echo $ul1
baidu.com/index.html
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url%/*}
[root@server ~]# echo $ul1
http://www.baidu.com
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url##*/}
[root@server ~]# echo $ul1
index.html
替换字符串
${parameter/pattern/string} 使用string代替第一个匹配的pattern
${parameter//pattern/string} 使用string代替所有匹配的pattern
[root@server ~]# str="Hi, girl, i am your friend."
[root@server ~]# echo $str
Hi, i am your friend.
[root@server ~]# echo ${str/i/I}
HI, i am your friend.
[root@server ~]# echo ${str//i/I}
HI, I am your frIend.
案例:批量修改文件名
-
需求:去掉所有文件的_finished字符信息。
-
准备测试数据
[root@server ~]# mkdir d2
[root@server ~]# cd d2
[root@server sub_str]# touch open_{1..5}_finish.jpg
[root@server sub_str]# touch open_{1..5}_finish.png
[root@server sub_str]# ll
total 0
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_1_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_1_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_2_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_2_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_3_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_3_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_4_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_4_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_5_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_5_finish.png
-
实现思路:
1. 可以通过 mv 命令来修改,如:
mv open_1_finish.jpg open_1.jpg
2. 我们要获取这个文件
f=open_1_finish.jpg
3. 通过字符串删除来实现
${f//_finish/}
-
功能实现:
# 查看当前目录下所有的文件
[root@server sub_str]# ls
open_1_finish.jpg open_2_finish.jpg open_3_finish.jpg open_4_finish.jpg open_5_finish.jpg
open_1_finish.png open_2_finish.png open_3_finish.png open_4_finish.png open_5_finish.png
# 循环这些文件并显示
[root@server sub_str]# for f in `ls`
> do
> echo ${f}
> done
open_1_finish.jpg
open_1_finish.png
open_2_finish.jpg
open_2_finish.png
open_3_finish.jpg
open_3_finish.png
open_4_finish.jpg
open_4_finish.png
open_5_finish.jpg
open_5_finish.png
# 通过循环来去掉 _finish 字符,但它并没有真正的修改磁盘中的文件,只是在内存中修改了
[root@server sub_str]# for f in `ls`; do echo ${f//_finish/}; done
open_1.jpg
open_1.png
open_2.jpg
open_2.png
open_3.jpg
open_3.png
open_4.jpg
open_4.png
open_5.jpg
open_5.png
[root@server sub_str]# ll
total 0
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_1_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_1_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_2_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_2_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_3_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_3_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_4_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_4_finish.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_5_finish.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_5_finish.png
# 结合 mv 命令来一个文件一个文件的修改 mv open_1_finish.jpg open_1.jpg
# open_1_finish.jpg 文件名称就是每次循环所得到的文件名 ${f}
# open_1.jpg 是通过 ${f//_finish/} 替换来到的
[root@server sub_str]# for f in `ls`; do mv ${f} ${f//_finish/}; done
[root@server sub_str]# for f in `ls`; do mv ${f} ${f##_finish}; done
[root@server sub_str]# for f in `ls`; do mv ${f} ${f%%_finish}; done
[root@server sub_str]# ll
total 0
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_1.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_1.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_2.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_2.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_3.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_3.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_4.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_4.png
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_5.jpg
-rw-r--r--. 1 root root 0 Mar 23 17:42 open_5.png
变量扩展
功能介绍
表达式 | 说明 |
---|---|
result=${parameter:-word} | 如果 parameter 变量值为空,会将word的值赋给result变量,parameter 变量值不变 |
result=${parameter:=word} | 如果 parameter 变量为空,会将 word 的值赋给 parameter 和 ressult变量 |
result=${parameter:?word} | 如果 parameter 变量为空,会将 word 作为标准错误输出。parameter 变量和 result 变量不变 |
result=${parameter:+word} | 如果 parameter 变量为空,什么都不做,否则 word 返回 |
使用示例
-
这四个扩展变量,都属于对变量的值进行判断和处理
# :- 判断变量如果值为空就返回后面字符信息 无值时临时赋值
[root@server ~]# echo $name
[root@server ~]# result=${name:-haha}
[root@server ~]# echo $name
[root@server ~]# echo $result
haha
# := 如果变量为空,则会将后面的字符赋值给变量并返回 无值时永久赋值
[root@server ~]# unset result
[root@server ~]# echo $name
[root@server ~]# echo $result
[root@server ~]# result=${name:=hehe}
[root@server ~]# echo $name
hehe
[root@server ~]# echo $result
hehe
[root@server ~]#
# :? 如果变量为空则错误信息返回后面的字符 无值时输出错误提示值
[root@server ~]# unset name result
[root@server ~]# echo $name
[root@server ~]# echo $result
[root@server ~]# result=${name:?haha}
-bash: name: haha
[root@server ~]# echo $result
[root@server ~]# echo $name
[root@server ~]#
# :+ 如果变量为空,什么都不做,否则返回后面字符 有值时临时替换
[root@server ~]# result=${name:+haha}
[root@server ~]# echo $name
[root@server ~]# echo $result
[root@server ~]# name=hehe
[root@server ~]# echo $name
hehe
[root@server ~]# result=${name:+haha}
[root@server ~]# echo $name
hehe
[root@server ~]# echo $result
haha
-
面试题:删除7天前的过期备份数据
#!/bin/bash
find ${path:-/tmp} -name "*.tar.gz" -type f mtime +7 | xargs rm -f
# find为查找文件命令
# ${path:-/tmp} :表示如果没有定义path则使用/tmp替代
# find不支持| 使用xargs命令表示管道符进行数据转换[root@localhost ~]# cat del.sh | 字符 -exec |xargs 参数find ${path:-/tmp} -name "*.bak" -type f -mtime +7 | xargs rm -f
如果没有定义path值,事先脚本中也没有设置变量:
[root@localhost ~]# cat del2.sh
find ${path} -name "*.tar.gz" -type f -mtime +7 | xargs rm -f
这样就不会删除指定目录,而是删除脚本运行目录中的文件。