简单的脚本实用技巧

归档压缩

[root@client ~]# tar -zcf boot.tar.gz /boot/* &> /dev/null

[root@client ~]# ls boot.tar.gz
boot.tar.gz

使用多个命令

[root@client ~]# ls ; who
anaconda-ks.cfg boot.tar.gz etc.tar.gz nginx-1.8.0 nginx-1.8.0.tar.gz
root tty1 2019-11-15 21:57
root pts/0 2019-11-15 22:04 (192.168.1.6)

要显示美元符,你必须在它前面放置一个反斜线。

[root@client ~]# echo "The cost of the item is \$15"
The cost of the item is $15

命令替换

[root@client ~]# testing=$(date)
[root@client ~]# echo $testing
2019年 11月 15日 星期五 22:15:57 CST
[root@client ~]# testing1=`date`
[root@client ~]# echo $testing1
2019年 11月 15日 星期五 22:16:19 CST

[root@client ~]# date +%y%m%d
191115

重定向。

输出重定向

[root@client ~]# date > testing

[root@client ~]# ls testing
testing

输入重定向

[root@client ~]# wc -l < /etc/passwd
23

[root@client ~]# cat << EOF
> SLDKF
> FDSJL
> EOF
SLDKF
FDSJL

[root@client ~]# sort < /etc/passwd

[root@client ~]# sort < /etc/passwd > passwd.bak

数字运算

[root@client ~]# expr 1 + 8
9
[root@client ~]# expr 1 + a
expr: 非整数参数

[root@client ~]# a=9
[root@client ~]# expr 8 + $a
17
[root@client ~]# echo $?
0
[root@client ~]# expr 1 + a
expr: 非整数参数
[root@client ~]# echo $?
2

[root@client ~]# a=90yu
[root@client ~]# expr 1 + $a
expr: 非整数参数
[root@client ~]# a=7.9
[root@client ~]# expr 1 + $a
expr: 非整数参数

可以用来判断变量的值是否为整数。

[root@client ~]# expr 9 \/ 3    #要使用\进行转义。
3

[root@client ~]# a=2
[root@client ~]# b=3

[root@client ~]# c=$(expr $a + $b)
[root@client ~]# echo $c
5

使用方括号

[root@client ~]# c=$[$a+$b]
[root@client ~]# echo $c
5

[root@client ~]# a=4
[root@client ~]# b=9
[root@client ~]# c=8
[root@client ~]# d=$[$a*($c-$b)]      #中括号里可以使用小括号的。
[root@client ~]# echo $d
-4

浮点数解决方案

[root@client ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1+2
3
3/2
1
1.1+3
4.1

bc命令是可以运算浮点数的。

[root@client ~]# bc -q
a=2
b=9
a+b
11
b/a
4

脚本中使用bc

[root@client ~]# var=$(echo "scale=4; 3.44/5"|bc)  #保留4位小数。
[root@client ~]# echo $var
.6880

bc 命令可以识别输入重定向,允许你将一个文件重定向到bc命令来处理,但这同样会叫人头疼,因为你还得将表达式放到文件中。

test命令

[root@client script]# test 1 -eq 2 && echo "yes" || echo "no"
no

[root@client script]# if test
> then
> echo "yes"
> else
> echo "no"
> fi
no

[root@client script]# [ "$a" \> "$b" ] && echo "yes" || echo "no"
no
[root@client script]# [ "$a" \< "$b" ] && echo "yes" || echo "no"    #比较符号需要转义。r
yes

[root@client script]# char="abc"
[root@client script]# [ -z "$char" ] && echo "yes" || echo "no"
no
[root@client script]# [ -n "$char" ] && echo "yes" || echo "no"
yes

双括命令允许你在比较的过程中使用高等数学表达式,test命令只能使用简单的算术操作,双括号命令提供了更多的数学符号,这些符号对于用过其他编程语言的程序员而言并不陌生,

if (( $var2 ** 2 > 90 ))

[root@client script]# [[ $USER == r* ]] && echo "root" || echo "no root"
root

 

[root@client script]# case $USER in
> root|ROOT)      |在这里是或的关系。
> echo "root"
> ;;
> esac
root

 [ -d $HOME ] && [-w $HOME/testing ]    #复合条件测试。

if (( $var11 ** 2 > 90 ))       

 

[root@glusterfs01 scpripts]# vi badtest1.sh
#!/bin/bash
for test in I don't konw if this'll work
do
echo "word:$test"
done

[root@glusterfs01 scpripts]# bash badtest1.sh
word:I
word:dont konw if thisll
word:work

 shell看到了列表值中的单引号并尝试使用它们来定义一个单独的数据值,这真是把事情搞得一团

[root@glusterfs01 scpripts]# vi badtest1.sh
#!/bin/bash
for test in I "don't" konw if "this'll" work
do
echo "word:$test"
done

[root@glusterfs01 scpripts]# vi badtest1.sh
#!/bin/bash
for test in I don\'t konw if this\'ll work
do
echo "word:$test"
done

[root@glusterfs01 scpripts]# bash badtest1.sh
word:I
word:don't
word:konw
word:if
word:this'll
word:work

for命令用空格来划分列表中的每个值,如果在单独的数据值中有空格,就必须用双引号将这些值圈起来。

[root@glusterfs01 scpripts]# vi badtest1.sh
#!/bin/bash
for test in "I don't" konw if "this'll work"
do
echo "word:$test"
done

[root@glusterfs01 scpripts]# bash badtest1.sh
word:I don't
word:konw
word:if
word:this'll work

从变量中读取列表

[root@glusterfs01 scpripts]# vi test4
#!/bin/bash
list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut"
for state in $list
do
echo "Have you ever visited $state"
done

[root@glusterfs01 scpripts]# bash test4
Have you ever visited Alabama
Have you ever visited Alaska
Have you ever visited Arizona
Have you ever visited Arkansas
Have you ever visited Colorado
Have you ever visited Connecticut

从命令读取值

[root@glusterfs01 scpripts]# vi states
Alabama
Alaska
Arizona
Arkansas
Colorado
Connecticut
Delaware
Florida
Georgia

[root@glusterfs01 scpripts]# for state in $(cat states)
> do
> echo "Visit beautiful $state"
> done
Visit beautiful Alabama
Visit beautiful Alaska
Visit beautiful Arizona
Visit beautiful Arkansas
Visit beautiful Colorado
Visit beautiful Connecticut
Visit beautiful Delaware
Visit beautiful Florida
Visit beautiful Georgia

更改字段分隔符

默认情况下,bash shell会将下列字符当作分隔符

空格,制表符,换行符。

要想更改字段分隔符,更改IFS的值,使其只能识别换行符,那就必须这么做。

[root@glusterfs01 scpripts]# vi test5b
#!/bin/bash
file="states"
IFS=$'\n'
for state in $(cat $file)
do
echo "Visit beautifull $state"
done
~

[root@glusterfs01 scpripts]# bash test5b
Visit beautifull Alabama
Visit beautifull Alaska
Visit beautifull Arizona
Visit beautifull Arkansas
Visit beautifull Colorado
Visit beautifull Connecticut
Visit beautifull Delaware
Visit beautifull Florida
Visit beautifull Georgia

用通配符读取目录

[root@glusterfs01 scpripts]# vi test6
#!/bin/bash
for file in /etc/*
do
if [ -d $file ]
then
echo -e "$file is \t\t a directory"
elif [ -f $file ]
then
echo "$file is a file"
fi
done

C语言风格的for命令

[root@glusterfs01 scpripts]# vi for5.sh
#!/bin/bash
for ((i=0; i<10; i++))
do
echo "The next number is $i"
done

[root@glusterfs01 scpripts]# bash for5.sh
The next number is 0
The next number is 1
The next number is 2
The next number is 3
The next number is 4
The next number is 5
The next number is 6
The next number is 7
The next number is 8
The next number is 9

使用多个变量

[root@glusterfs01 scpripts]# vi for6.sh
#!/bin/bash
for ((a=1, b=10; a<=10; a++, b--))
do
echo "$a-$b"
done

[root@glusterfs01 scpripts]# bash for6.sh
1-10
2-9
3-8
4-7
5-6
6-5
7-4
8-3
9-2
10-1

while命令

while命令某种意义上是if-then语句和for循环的混杂体,while命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的是退出状态码0,它会在每次迭代的一开始测试test命令,在test命令返回非零退出状态码时。while命令会停止执行那组命令

[root@glusterfs01 scpripts]# vi while1.sh
#!/bin/bash
var=10
while [ $var -gt 0 ]
do
echo $var
var=$[ $var-1 ]
done

[root@glusterfs01 scpripts]# bash while1.sh
10
9
8
7
6
5
4
3
2
1

使用多个测试命令

[root@glusterfs01 scpripts]# vi while2.sh
#!/bin/bash
var1=10
while echo $var1 && [ $var1 -gt 0 ]  #第一个测试简单地显示了var1变量的值,第二个测试用方括号来判断var1变量的值。在循环内部,echo语句会显示一条简单的消息,说明循环被执行了,注意当你运行本例时输出是如何结束的。
do
echo "This is inside the loop"
var1=$[ $var1-1 ]
done

[root@glusterfs01 scpripts]# bash while2.sh
10
This is inside the loop
9
This is inside the loop
8
This is inside the loop
7
This is inside the loop
6
This is inside the loop
5
This is inside the loop
4
This is inside the loop
3
This is inside the loop
2
This is inside the loop
1
This is inside the loop
0

until命令

和while命令工作的方式相反,until命令要求你指定一个通常返回非零退出状态码的测试命令,只有测试命令的退出状态码不为0,bash shell才会执行循环中列出的命令。

[root@glusterfs01 scpripts]# vi until.sh
#!/bin/bash
var1=100
until [ $var1 -eq 0 ]
do
echo "Inside the loop: $var1"
var1=$[ $var1-25 ]
done

[root@glusterfs01 scpripts]# bash until.sh
Inside the loop: 100
Inside the loop: 75
Inside the loop: 50
Inside the loop: 25

[root@glusterfs01 scpripts]# vi until.sh
#!/bin/bash
var1=100
until echo $var1 && [ $var1 -eq 0 ]
do
echo "Inside the loop: $var1"
var1=$[ $var1-25 ]
done

[root@glusterfs01 scpripts]# bash until.sh
100
Inside the loop: 100
75
Inside the loop: 75
50
Inside the loop: 50
25
Inside the loop: 25
0

嵌套循环

[root@glusterfs01 scpripts]# vi for10.sh
#!/bin/bash
for (( i=1; i<=5; i++ ))
do
echo "Starting loop $i"
for (( y=1; y<=5; y++ ))
do
echo " Inside loop: $y"
done
done

Starting loop 1
Inside loop: 1
Inside loop: 2
Inside loop: 3
Inside loop: 4
Inside loop: 5
Starting loop 2
Inside loop: 1
Inside loop: 2
Inside loop: 3
Inside loop: 4
Inside loop: 5
Starting loop 3
Inside loop: 1
Inside loop: 2
Inside loop: 3
Inside loop: 4
Inside loop: 5
Starting loop 4
Inside loop: 1
Inside loop: 2
Inside loop: 3
Inside loop: 4
Inside loop: 5
Starting loop 5
Inside loop: 1
Inside loop: 2
Inside loop: 3
Inside loop: 4
Inside loop: 5

[root@glusterfs01 scpripts]# vi for10.sh
#!/bin/bash
var1=3
while [ $var1 -ge 0 ]
do
echo "Starting loop $var1"
for (( y=1; y<=3; y++ ))
do
echo " Inside loop: $y"
done
var1=$[ $var1 -1 ]
done

[root@glusterfs01 scpripts]# bash for10.sh
Starting loop 3
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting loop 2
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting loop 1
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting loop 0
Inside loop: 1
Inside loop: 2
Inside loop: 3

[root@glusterfs01 scpripts]# vi for10.sh
doq
#!/bin/bash
var1=3
until [ $var1 -eq 0 ]
do
echo "Starting loop $var1"
for (( y=1; y<=3; y++ ))
do
echo " Inside loop: $y"
done
var1=$[ $var1 -1 ]
done

[root@glusterfs01 scpripts]# bash for10.sh
Starting loop 3
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting loop 2
Inside loop: 1
Inside loop: 2
Inside loop: 3
Starting loop 1
Inside loop: 1
Inside loop: 2
Inside loop: 3

循环处理文件

[root@glusterfs01 scpripts]# vi forfile.sh
#!/bin/bash
IFS_OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
echo "Values in $entry -"
IFS=:
for value in $entry
do
echo " $value"
done
done

[root@glusterfs01 scpripts]# bash forfile.sh
Values in root:x:0:0:root:/root:/bin/bash -
root
x
0
0
root
/root
/bin/bash
Values in bin:x:1:1:bin:/bin:/sbin/nologin -
bin
x
1
1
bin
/bin
/sbin/nologin

控制循环

  • break
  • continue

break命令是退出循环的一个简单方法,可以用break命令来退出任意类型的循环,包括while和until循环。

跳出单个循环

[root@glusterfs01 scpripts]# vi test17.sh
#!/bin/bash
for var1 in 1 2 3 4 5 6 7 8 9 10
do
if [ $var1 -eq 5 ]
then
break
fi
echo "Iteration number: $var1"
done
echo "The for loop is completed"

[root@glusterfs01 scpripts]# bash test17.sh
Iteration number: 1
Iteration number: 2
Iteration number: 3
Iteration number: 4
The for loop is completed

[root@glusterfs01 scpripts]# vi test17.sh
#!/bin/bash
var1=10
while [ $var1 -le 10 ]
do
if [ $var1 -eq 5 ]
then
break
fi
echo "Iteration number: $var1"
var1=$[ $var1-1 ]
done

echo "The for loop is completed"
~

[root@glusterfs01 scpripts]# bash test17.sh
Iteration number: 10
Iteration number: 9
Iteration number: 8
Iteration number: 7
Iteration number: 6
The for loop is completed

跳出内部循环

在处理多个循环时,break 命令会自动终止你所在的最内层的循环。

[root@glusterfs01 scpripts]# vi test20.sh
#!/bin/bash
for ((a=1; a<4; a++))
do
echo "Outer loop: $a"
for ((b=1; b<100; b++))
do
if [ $b -eq 5 ]
then
break
fi
echo " Inner loop: $b"
done
done

[root@glusterfs01 scpripts]# bash test20.sh
Outer loop: 1
Inner loop: 1
Inner loop: 2
Inner loop: 3
Inner loop: 4
Outer loop: 2
Inner loop: 1
Inner loop: 2
Inner loop: 3
Inner loop: 4
Outer loop: 3
Inner loop: 1
Inner loop: 2
Inner loop: 3
Inner loop: 4

跳出外部循环

break n  其中n指定了要跳出的循环层级,默认情况下,n为1,表明跳出的是当前的循环,如果你将n设为2,break命令就会停止下一级的外部循环。

[root@glusterfs01 scpripts]# vi test21.sh
#!/bin/bash
for ((a=1; a<4; a++))
do
echo "Outer loop: $a"
for ((b=1; b<100; b++))
do
if [ $b -gt 4 ]
then
break 2
fi
echo " Inner loop: $b"
done
done
~

[root@glusterfs01 scpripts]# bash test21.sh
Outer loop: 1
Inner loop: 1
Inner loop: 2
Inner loop: 3
Inner loop: 4

continue命令

可以提前中止某次循环中的命令,但并不会完全终止整个循环,可以在循环内部设置shell不执行的命令条件,这里有个在for循环中使用continue命令的简单例子。

[root@glusterfs01 scpripts]# vi test25.sh
#!/bin/bash
for ((var1=1; var1<15; var1++))
do
if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
then
continue
fi
echo "Iteration number: $var1"
done

[root@glusterfs01 scpripts]# bash test25.sh
Iteration number: 1
Iteration number: 2
Iteration number: 3
Iteration number: 4
Iteration number: 5
Iteration number: 10
Iteration number: 11
Iteration number: 12
Iteration number: 13
Iteration number: 14

 处理循环的输出

[root@localhost scrips]# cat test23.sh
#!/bin/bash
for file in /etc/*
do
if [ -d $file ]
then
echo "$file is a directory"
else
echo "$file is a file"
fi
done > output.txt      #输出重定向到一个文件里。而不是显示在屏幕上。

 

[root@localhost scrips]# vi test24.sh

#!/bin/bash
for ((a=1; a<10; a++))
do
echo "The number is $a"
done > output1.txt
echo "The command is finished."

[root@localhost scrips]# bash test24.sh
The command is finished.
[root@localhost scrips]# cat output1.txt
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8
The number is 9

 

[root@localhost scrips]# vi test25.sh

#!/bin/bash
for state in "North dakota" connecticpu illinos alabama tennessee
do
echo "$state is the next place to go"
done | sort                      #通过管道将结果交给另一个命令,做为另一个命令的输入。
echo "This complets our travels"

[root@localhost scrips]# bash test25.sh
alabama is the next place to go
connecticpu is the next place to go
illinos is the next place to go
North dakota is the next place to go
tennessee is the next place to go
This complets our travels

 

[root@localhost scrips]# cat test26.sh       #查找可执行文件。
#!/bin/bash
IFS=:
for folder in $PATH
do
echo "$folder:"
for file in $folder/*
do
if [ -x $file ]
then
echo " $file"
fi
done
done

 创建多个用户帐号

[root@localhost scrips]# cat test27.sh
#!/bin/bash
input="users.csv"
while IFS="," read -r userid name
do
echo "adding $userid"
useradd -c "$name" -m $userid
done < "$input"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-11-15 23:21  星火撩原  阅读(232)  评论(0编辑  收藏  举报