使用名为shellceshi.sh的脚本用来测试,后续的“代码部分”在没有特别指明时默认指shellceshi.sh的代码
一、eval用法
1、调用最后一个参数
代码(后续用相同格式表示代码):
echo "最后一个参数为"$(eval echo \$$#)""
运行(后续用相同格式表示终端)
$ ./shallceshi.sh a b c d
最后一个参数为d
如果想得到倒数第二个参数
echo "倒数第二个参数为"$(eval echo \$$[$#-1])""
$ ./shallceshi.sh a b c d
倒数第二个参数为c
2、可以定义函数
_set_var() {
echo ceshi
}
eval "$1(){ _set_var; }" #定义名为输入参数1的函数
set_var
$ ./shallceshi.sh set_var
ceshi
二、shift用法
shift n 移除前n个参数,不加n则默认移除第一个参数,相当于shift 1,且移除的参数不再可用,原来的所有参数会前移
shift
echo $@
$ ./shallceshi.sh a b c d
b c d
使用\给函数传递多个参数的方法
func() {
while [ -n "$1" ]; do #参数不空就继续运行
echo "当前参数为$1"
shift
done
}
func\
a\
b\
c\
$ ./shallceshi.sh
当前参数为a
当前参数为b
当前参数为c
三、for循环
for读取列表中的值
sss="1 2 3 4 5"
for a in $sss 6 #a依次取in后面的值
do
echo $a
done
$ ./shallceshi.sh
1
2
3
4
5
6
过程中,默认使用空格、制表符、换行符作为数据分隔符,如果想使用其他符号作为分隔符,需要更改IFS的值。
例如:
b=1,2,3,4,5
for a in $b
do
echo $a
done
此时运行结果为
$ ./shallceshi.sh
1,2,3,4,5
如果我们想输出为
$ ./shallceshi.sh
1
2
3
4
5
那么设置逗号为分隔符(IFS)就可以满足上述要求
oldIFS=IFS #保留原IFS值
IFS=,
b=1,2,3,4,5
for a in $b
do
echo $a
done
IFS=oldIFS #IFS恢复为默认值
另外,可以使用类C循环体
for(( ; ; )) #((这里的条件、变量计算直接按C来写,不用加$,语句可以全空))
do
#命令
done
四、unset用法
用来删除变量,值得注意的是shell脚本中,指令本身可以用作变量。
aaa="echo qwe"
bbb=asd
unset=$aaa
unset bbb
echo $unset $bbb
$ ./shallceshi.sh
echo qwe
如果想执行"echo qwe"语句的话,把第五行的echo换成eval即可。
五、source、export命令
运行脚本文件有2种方式:
(1) $./shellceshi.sh
(2) $source shellceshi.sh
第一种方法是新建一个子shell运行脚本,涉及的变量会在子shell运行结束之后消失。如果需要将变量传递给子系统,需要使用export指令,例如
shellceshi.sh代码
export aaa=hello
./shallceshi2.sh
shallceshi2.sh代码
echo $aaa
$ ./shallceshi.sh
hello
第2种方法是读出脚本语句到当前shell执行,故脚本变量会保留在当前shell。以下代码帮助理解:
shellceshi.sh代码
export aaa=hello
./shallceshi2.sh
echo $aaa
shellceshi2.sh代码
echo $aaa
aaa="hello world!"
echo $aaa
$ ./shallceshi.sh
hello
hello world!
hello
显然shellceshi2.sh对参数aaa的更改没有传递给shellceshi.sh脚本,如果需要实现传递,则将shellceshi.sh代码改为:
export aaa=hello
source shallceshi2.sh
echo $aaa
$ ./shallceshi.sh
hello
hello world!
hello world!
其他用法,
export -n 变量 表示取消将该变量传递给子系统
export -p 列出当前所有环境变量
export - -\可以用来传递多个变量(注意后续每行的\都不能少,- -可以省略不写)
shellceshi.sh代码
aaa=hello #可以先赋值,也可以在传递时赋值
export --\
aaa\
bbb="hello2"
./shallceshi2.sh
shallceshi2.sh代码
echo $aaa
echo $bbb
$ ./shallceshi.sh
hello
hello2
六、#* 、##* 、%*、%%*的用法
(1) ${变量#*[符号]} 删除变量中第一次出现该符号的左边部分(包括该符号也会删除)
(2) ${变量##*[符号]} 删除变量中最后一次出现该符号的左边部分
(3) ${变量%[符号]*} 删除变量中最后一次出现该符号的右边部分
(4) ${变量%%[符号]*} 删除变量中第一次出现该符号的右边部分
(5) ${#变量} 计算变量字符长度
file="/dir1/dir2/dir3/my.file.txt"
echo $file
a="${file#*r}"
echo $a
b="${file##*r}"
echo $b
c="${file%.*}"
echo $c
d="${file%%i*}"
echo $d
$ ./shallceshi.sh
/dir1/dir2/dir3/my.file.txt
1/dir2/dir3/my.file.txt
3/my.file.txt
/dir1/dir2/dir3/my.file
/d
注:
1)、符号可以写为[1-9]
表示出现任意1-9的数字时,[a-c]
表示任意a-c字母,[1 c]
表示1或者c。
2)、变量可以从参数获取,直接数字表示即可
其他用法:
(5)${变量#字符串}从变量左边最小匹配字符串并删除
${变量##字符串}从变量左边最大匹配字符串并删除
${变量%字符串}从变量右边最小匹配字符串并删除
${变量%%字符串}从变量右边最大匹配字符串并删除
sss=abcabcdabcdeabcdefabcdefg
echo $sss
ssss="${sss#b}" #左起第一个字符不是b,故不能匹配到,不进行任何操作
echo $ssss
sss2="${sss#a*c}" #删除左起匹配到a......c的最小串
echo $sss2
sss3="${sss##a*c}" #删除左起匹配到a......c的最大串
echo $sss3
sss4="${sss%d*g}" #删除右起匹配到d......g的最小串
echo $sss4
sss5="${sss%%d*g}" #删除右起匹配到d......g的最大串
echo $sss5
$ ./shallceshi.sh
abcabcdabcdeabcdefabcdefg
abcabcdabcdeabcdefabcdefg
abcdabcdeabcdefabcdefg
defg
abcabcdabcdeabcdefabc
abcabc
(6)${变量:数字a:数字b}:在变量中提取第a个字符后的b个字符,第(a+1)个字符是提取的第一个字符:
(7)可以对变量里的字符串作替换:
${变量/被替换的字符/新字符} 仅替换第一个
${变量//被替换的字符/新字符} 替换所有字符
file="/dir1/dir2/dir3/my.file.txt"
echo $file
e=${file:3:4}
echo $e
f=${file/dir/path}
echo $f
g=${file//dir/path}
echo $g
$ ./shallceshi.sh
/dir1/dir2/dir3/my.file.txt
r1/d
/path1/dir2/dir3/my.file.txt
/path1/path2/path3/my.file.txt
七、数值运算方法
(1)let 计算式、[计算式] 、((计算式)) 计算一般的整数型表达式
(2)expr用法:`expr 计算式` 需要注意:计算式前后加反引号`,计算式符号和数值要用空格隔开,乘号*前需要去义符号\
有多个表达式时,取值为最后一个表达式的值,如:
a=100
b=$[a+3**3] #这里的**表示乘方
c=$((a/4))
let d=(a-1,a-2,a-3)
e=`expr $a + 2 \* 8`
echo -e "$b\n$c\n$d\n$e" #加入-e之后可以使用\n来表示换行
$ ./shallceshi.sh
127
25
97
116
变量i自加1可以使用多种方法:
#第一种方法
i=$[$i+1] #中括号里的$可以省略,写成i=$[i+1]
#第二种方法
i=$(($i+1)) #也可以写成i=$((i+1))
#第三种方法
let i+=1
#第四种方法
let i++
#第五种方法
i=`expr $i + 1`
#第六种方法
((i++))
(3)bc的用法,可以进行浮点运算、进制转换、高阶运算
a)浮点运算时设定小数精度,scale=小数位数
b)进制转换,obase=目标进制,ibase=当前进制
c)sqrt(被开方数)等高阶运算
a=100
echo "scale=3;100/8"|bc
f=`echo "scale=3;100/8"|bc` #如果需要赋值
echo f=$f
g=`echo "obase=10;ibase=2;$a"|bc` #二进制转十进制
echo $g
h=`echo "obase=2;ibase=10;$a"|bc` #十进制转二进制
echo $h
i=`echo "scale=1;sqrt($a)"|bc`
echo $i
$ ./shallceshi.sh
12.500
f=12.500
4
1100100
10.0
八、^ 的一种用法
[^A-Z]表示除了不包含大写字母,^取反;^[A-Z]表示以大写字母开头
var="${1//[^a-zA-Z]/_}" #将输入参数1中的所有非字母转换成下划线
echo $var
$ ./shallceshi.sh ^^Da@da%sd\ a
__Da_da_sd_a
九、&& 、||的用法
(1) 命令1 && 命令2 只有当命令1为真时(返回值为0)才执行后面的命令2,多个&&串接时同理
(2) 命令1 || 命令2 只有当命令1为假时(返回值为非0)才执行后面的命令2,多个||串接时同理
a=true
b=false
[ "$a" == "true" ] && echo a is true
[ "$b" == "true" ] && echo b is true
[ "$a" == "true" ] || echo a is false
[ "$b" == "true" ] || echo b is false
[ "$a" == "true" ] && [ "$b" == "true" ] || echo pass
$ ./shallceshi.sh
a is true
b is false
pass
例如,判断一个输入是否为数字
read a
echo $a | grep -q '[^0-9]' && echo no || echo yes
十、grep的用法
语法:grep -选项 ‘搜索内容串’ 待搜索文件
-a 以文本文件方式搜索
-c 计算找到的符合行的次数
-i 忽略大小写
-n 顺便输出行号
-v 反向选择,即搜索没有该字符串的行
-q 不打印输出结果
-E 大写 ,搜索内容串支持正则
-r 搜索当前文件夹下所有文件
-l 只显示文件名称
例如,shallceshi.sh内容
a
ab
Abc
aBcd
hello
hello world
终端运行(由于要用引号只能用这种方式写了):
$ grep -c 'a' shallceshi.sh
3
$ grep 'a' shallceshi.sh -ci #选项也可以置于后面
4
$ grep 'a' shallceshi.sh -n
1:a
2:ab
4:aBcd
$ grep -v 'a' shallceshi.sh
Abc
hello
hello world
搜索字符可以使用[ ]表示搜索合集,表示含有其中某一个字符。例如[b-d]表示bcd三个字符中的一个,[3c]表示3或c;符号^在[ ]内部时表示取反,[^ad]表示除了a、d之外的符号
$ grep '[b-d]' shallceshi.sh
ab
Abc
aBcd
hello world
$ grep '[^ac]' shallceshi.sh
ab
Abc
aBcd
hello
hello world
行首字符^与行尾字符$,表示位置而不是字符
$ grep -n '^[a]' shallceshi.sh #搜索以a开头的字符
1:a
2:ab
4:aBcd
$ grep -n '[o]$' shallceshi.sh #搜索以o结尾的字符
6:hello
$ grep -n '^$' shallceshi.sh #搜索空行
5:
任意一个字符.与重复字符*
字符.表示一个且一定存在,例如'a.c'
表示aac、abc、acc、adc…
字符*表示存在0个以上的重复字符,例如'ab*c'
表示ac、abc、abbc、abbbc…
'a.*c'
表示 a(任意个任意字符,包括空格等)c,如ac、akfsc、adsf c…
如果需要对重复字符的个数进行限制,使用'字符\{下限次数,上限次数\}'
,如'a\{1,2\}'
表示a出现1次或者2次,上下限次数可以不写表示无上下限制次数
$ grep -in 'a.c' shallceshi.sh
3:Abc
4:aBcd
$ grep -in 'el\{1\}o' shallceshi.sh #没有含elo字符串的行
$ grep -in 'el\{2\}o' shallceshi.sh #搜索带有ello的字符串
6:hello
7:hello world
扩展grep -E的用法,也可以写作egrep。举例说明
$ grep -v '^A' shallceshi.sh | grep -v '^$' #去除以A开头的行和空行(未修改原文件)
a
ab
aBcd
hello
hello world
$ grep -vE '^A|^$' shallceshi.sh #两者等同,输出结果一样
a
ab
aBcd
hello
hello world
几个扩展特殊符号(暂未验证):
+,表示一个或多个重复字符
?,表示0个或一个字符
| ,表示或关系,比如'gd|good|dog'
表示有gd,good或dog的串
(),将部分内容合成一个单元组。比如要搜索glad或good可以这样'g(la|oo)d'
,()的好处是可以对小组使用+ ? |等
比如要搜索A和C开头结尾,中间有至少一个(xyz)的串,可以这样:'A(xyz)+C'
十一、拓展符号比较大小
-eq 等于(equal)
-ne 不等于(no equal)
-gt 大于(greater than)
-lt 小于(less than)
-ge 大于等于(greater and equal)
-le 小于等于(less and equal)
echo 比较两个数的大小
echo -n a=
read a
echo -n b=
read b
if [ $a -gt $b ] ; then
echo a大于b
elif [ $a -eq $b ] ;then
echo a等于b
else
echo a小于b
fi
十二、sed的用法
这篇写的很详细 https://blog.csdn.net/wdz306ling/article/details/80087889#commentBox
总结一下,格式为 sed -选项 ‘要处理哪些行如何处理处理内容’ 文件名
如$ sed -n '1insert' shallceshi.sh
表示在shallceshi.sh文件的第一行之前插入nsert
选项:
-i 修改并保存到原文件(默认只预览,不作实质修改)
-n 只显示处理过的行(默认显示全部文件内容)
要处理哪些行:
不写则表示所有行
数字x 处理第x行
数字x,数字y 处理第x到y行
数字x~数字y 处理第(x+ny)行,n=0,1,2,3…
可以匹配得到行,格式为 /匹配内容/ 即处理有匹配内容的行
如何处理:
a… 向某行(可以指定,写在a前面,也可以匹配得到)之后插入一行,内容为…
i… 向某行(可以指定,写在i前面,也可以匹配得到)之前插入一行,内容为…
c… 将某行(可以指定,写在c前面,也可以匹配得到)替换,内容为…
d 删除某行(可以指定,写在d前面,也可以匹配得到)
p 打印某行(可以指定,写在p前面,也可以匹配得到),通常配合-n使用
= 在某行之前插入该行行号,通常配合-n使用
s/字符串1/字符串2/替换第几个 将该行中的字符串1替换成字符串2,默认替换第一个,g表示全部替换(替换的分隔符号/可以替换成#,防止字符串中含有/时造成冲突)
如$ sed '/echo/s/asd/zxc/2' shallceshi.sh
表示对于shallceshi.sh文件,匹配含有echo的行,将行中的第二个asd替换成zxc
$ sed '/hello/,$d' shallceshi
删除匹配到hello及之后的所有行
注:
1、匹配内容:字符串可以用单个任意字符.、\{数字\}表示字符个数或任意个重复字符*、行首符号^、行尾符号$、[0-9]范围(中括号里的^表示取反)、&或\1表示匹配到的内容,在搜索行时在/后加!表示取反,/,+1表示匹配的行和下一行
2、文件名可以使用`命令` 方式得到,例如sed -i '1ihello' `ls`
表示在当前所有文件的第一行之前插入一行,内容为hello
如 $ sed 's/[^0-9]/_/g' shallceshi.sh
表示将所有非数字替换成下划线
十三、:的用法
https://www.cnblogs.com/nkwy2012/p/9171408.html