shell 脚本

文件重定向

标准输入stdin  -  0 (默认情况)

标准输出stdout  -  1

标准错误 stderr  -  2

将输出和错误重定向到不同的文件

command 1>out.txt 2>error.txt

command >out.txt 2>error.txt

检查文件内容

       cat error.txt

重定向两个流到同一个文件

       command >>out_err.txt 2>>out_err.txt

‘>>’表示附加文件,而不是覆盖文件

      

       command >out_err.txt 2>&1

    错误输出将被重定向到流1,该流被重定向到同一个文件。

重定向工具‘管道‘,使用|(管道)符号,通常重定向stdout流

在文件中搜索‘Hello‘字串,使用grep命令

       grep Hello text_file.txt

重定向一个命令的stdout到另一个命令的stdin流

       # fdisk -l | grep “Disk /dev”

把fdisk stdout重定向到了grep stdin.

运行脚本

       ./note.sh

运行当前文件夹下的文件note.sh

       # cat note.sh

    文件内容:

     #!/bin/bash

echo “phone number ?”

默认的用户shell将调用/bin/bash,而只有在那个时候,脚本中的命令才会被执行。

变量

       Bash shell中,用$(美元)符合来表明一个变量

#!/bin/bash

echo “Phone number ?”

read phone

echo “Name ?”

read name

echo “Issue?”

read issue

运行文件: # ./note.sh

将输入内容重定向到文件data.txt:

echo “$phone/$name/$issue”>>data.txt

查看文件note.sh最后两行:

# tail -2 note.sh

read issue

echo “$phone/$name/$issue”>>data.txt

添加日期

       date “+%Y-%m-%d %H:%M:%S”

文件中添加日期:`(反引号,不是单引号,和波浪号~同一个键位)

       now = `date “+%Y-%m-%d %H:%M:%S”`

完整脚本

#!/bin/bash

now = `date “+%Y-%m-%d %H:%M:%S”`

echo “Phone number ?”

read phone

echo “Name ?”

read name

echo “Issue?”

read issue

       echo “$phone/$name/$issue”>>data.txt

改进,使用-p键加上信息,再使用循环

       #!/bin/bash

       while true

       do

                     read -p “Phone number: ” phone

                     now = `date “+%Y-%m-%d %H:%M:%S”`

                     read -p “Name: ” name

                     read -p “Issue: ” issue

                     echo “$now/$phone/$name/$issue”>>data.txt

       done

按[Ctrl]+[C]退出循环

使用cut将重定向结果切成一块一块的(按‘/‘分割),打印第二个字段,然后再排序

cat data.txt | cut -d”/” -f2 | sort

统计唯一条目,只需要添加-c键到uniq命令

cat data.txt | cut -d”/” -f2 | sort | uniq -c

最后更新,脚本:

#!/bin/bash

while true

do

       read -p "Phone number: " phone

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

       read -p "Name: " name

       read -p "Issue: " issue

       echo "$now/$phone/$name/$issue">>data.txt

       echo "====== we got calls from ======"

       cat data.txt | cut -d"/" -f2 | sort | uniq -c

       echo "--------------------------------"

done

#!告诉系统其后路径所指定的程序即是解释此脚本文件的shell程序。

像#!/bin/sh,也可以改为#!/bin/bash

执行脚本:

       ./note.sh

       一定要写成./note.sh,而不是note.sh,运行其他二进制也一样。

       直接写成note.sh, Linux系统会去PATH里寻找有没有叫note.sh的文件,而只有/bin,/sbin,/usr/bin,/usr/sbin等在PATH里,而当前目录通常不在PATH里,所以写成note.sh是会找不到命令的,要用./note.sh告诉系统,在当前目录找。

       可直接运行解释器:

       /bin/sh note.sh

A,定义变量时,变量名和等号之间不能有空格

B,使用变量,在变量名前面加美元符号即可

your_name=’qinjx’

echo $your_name

echo ${your_name}

加花括号是为了帮助解释器识别变量的边界

C,删除变量:使用unset命令

       unset your_name

d,使用help命令查看保留的关键字

e,只读变量:使用readonly命令定义只读变量

f,使用双引号或单引号来定义字符串,双引号里可以有变量,但单引号里的变量是无效的,会原样输出。

G,双引号里可以出现转义字符: \n \t \’’

H,注释一行:以 # 开头的行就是注释

I,注释多行:

:<<EOF

注释内容

注释内容

注释内容

EOF

EOF也可以换成其他符号

J,定义数组:用括号来表示数组,数组元素用"空格"符号分割开

       array_name=(value0 value1 value2 value3)

读取数组,使用下标:

valuen=$(array_name[n])

获取数组所有元素,使用@符号:

echo ${array_name[@]}

获取数组长度:

Length=${#array_name[@]}

Length=${#array_name[*]}

获取数组单个元素的长度:

Length=${#array_name[n]}

#!/bin/bash

array_name=(A B "C" D)

echo ${array_name[@]}

echo ${array_name[*]}

echo ${array_name[0]}

echo ${array_name[1]}

echo ${array_name[2]}

echo ${array_name[3]}

运行结果:

A B C D

A B C D

A

B

C

D

表达式:

val=`expr 2 + 2`

echo "sum is $val"

表达式和运算符之间要有空格,必须写成’2 + 2‘;表达式要用反引号` `包含.

#!/bin/bash

a=10

b=20

if [ $a == $b ]

then

       echo "a equal b"

fi

if [ $a != $b ]

then

       echo "a not equal b"

fi

val=`expr $a \* $b`

echo "a * b is $val"

运行结果:

a not equal b

a * b is 200

算术运算符:‘+  -  *  /  %(取余)  =(赋值)  ==  !=’ 

关系运算符只支持数字,不支持字符串,除非字符串的值时数字。运算符:

‘-eq -ne -gt -lt -ge -le’

布尔运算符:‘!(非) -o(或) -a(与) ’

#!/bin/bash

if [ $a -lt 20 -a $b -gt 10 ]

then

       echo "a less than 20 and b great than 10: return True"

else

       echo "a not less than 20 and b not great than 10: return False"

fi

运行结果:

a less than 20 and b great than 10: return True

逻辑运算符:‘&&(逻辑与)  ||(逻辑或)’

字符串运算符:‘=  !=  -z(检测字符串长度是否为0,为0返回true)  -n(检测字符串长度是否不为0,不为0返回true)  $(检测字符串是否为空,不为空返回true)’

#!/bin/bash

val1="abc"

val2="efg"

if [ -z $varl ]

then

       echo "-z $val1 length is not zero"

else

       echo "-z $val1 length is  zero"

fi

if [ $val1 != $val2 ]

then

       echo "$val1 != $val2: a not equal to b"

else

       echo "$val1 = $val2: a equal to b"

fi

运行结果:

-z abc length is not zero

abc != efg: a not equal to b
 
文件检测运算符:
-b file 检测文件是否是块设备文件,如果是,则返回true
-c file 检测文件是否是字符设备文件
-d file 检测文件是否是目录
-f file 检测文件是否是普通文件,如果是,则返回true
-g file 检测文件是否设置了SGID位
-k file 检测文件是否设置了粘着位
-p file 检测文件是否是有名管道,如果是,则返回true
-u file 检测文件是否设置了SUID位,如果是,则返回true
-r file 检测文件是否可读,如果是,则返回true
-w file 检测文件是否可写,如果是,则返回true
-x file 检测文件是否可执行,如果是,则返回true
-s file 检测文件是否为空(文件大小是否大于0),不为空返回true
-e file 检测文件(包括目录)是否存在,如果是,则返回true
 
#!/bin/bash
file="/var/www/runoob/test.sh"
if [ -e $file ]
then
        echo "file exist"
        if [ -r $file ]
        then
               echo "file can read"
        else 
               echo "file can not read"
        fi
else 
        echo "file not exist"
fi
 
if [ -r $file ]
then
        echo "file can read"
else 
        echo "file can not read"
fi
 
运行结果:
file not exist

file can not read
 
显示换行:echo -e "ok! \n" #-e开启转义, \n换行
显示不换行:echo -e "ok! \c" #-e开启转义,\c不换行
原样输出,不转义或取变量(单引号):echo '$name\"'
 
#!/bin/bash
echo `date`
echo -e "ok! \c" #-e开启转义,\c不换行
echo "It is a test"
echo -e "ok! \n" #-e开启转义, \n换行
echo "It is a test"
echo '$name\"'
 
运行结果:
Mon 29 Mar 2021 12:52:54 PM UTC

ok! It is a test

ok! 



It is a test

$name\"
 
printf格式控制输出:
printf “%-10s %-8s %-4s\n” name sex weight(kg)
printf “%-10s %-8s %-4.2f\n” guojing male 66.1234
 
printf转义序列:
\a 警告字符
\b 后退
\c 抑制换行
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\\ 一个字面上的反斜杠字符
\ddd 表示1到3位八进制值的字符,仅在格式字符串中有效
\0ddd 表示1到3位八进制值字符
 
Shell test命令:
数值测试: -eq  -ne  -gt  -ge  -lt  -le 
字符串测试: =  !=  -z  -n
文件测试:-e  -r  -w  -x  -s  -d  -f  -c  -b 
 
#!/bin/bash
num1=100
num2=200
if test $[num1] -eq $[num2]
then 
        echo "they are equal"
else 
        echo "they are not equal"
fi
 
result=$[num1+num2]
echo "result is $result"
 
num1="run1oob"
num2="runoob"
if test $num1 = $num2
then
        echo "they are equal"
else
        echo "they are not equal"
fi
 
if test -e ./bash
then 
        echo "file is existed"
else
        echo "file is not existed"
fi
 
运行结果:

they are not equal
result is 300
they are not equal
file is not existed

 
shell流程控制:
if [ $(ps -ef | grep -c “ssh”) -gt 1 ]; then echo “true”; fi
 
for str in this is a string
do
        echo $str
done
 
int=1
while(( $int <= 5 ))
do
        echo $int
        let "int++"
done
 
a=0
until [ ! $a -lt 10 ]
do
        echo $a
        a=`expr $a + 1`
done
 
运行结果:

this
is
a
string
1
2
3
4
5
0
1
2
3
4
5
6
7
8
9

 
 
echo "input number 1-4:"
echo "your input:"
read aNum
case $aNum in
        1) echo "your input 1"
        ;;
        2) echo "your input 2"
        ;;
        3) echo "your input 2"
        ;;
        4) echo "your input 4"
        ;;
        *) echo "your input not in 1-4"
        ;;
esac
 
运行结果:

input number 1-4:
your input:
your input not in 1-4

 
break 命令:跳出所有循环
continue 命令:跳出当前循环
 
带参数的函数
在函数体内部,通过$n的形式来获取参数的值,$10不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取。
函数返回值在调用函数后通过 $? 来获得
 
#!/bin/bash
funWithReturn(){
        echo "the first param $1"
        echo "the second param $2"
        echo "the third param $3"
        echo "the tenth param $10"
        echo "the tenth param ${10}"
        echo "the eleventh param ${11}"
        echo "the count of params: $# !"
        echo "output all params as one string: $* !"
}
funWithReturn 1 2 3 4 5 6 7 8 9 34 73
echo $?
 
function fun1(){
        echo "this is the first function"
        return `expr 1 + 1 `
}
fun1
echo $?
echo $?
 
运行结果:
the first param 1

the second param 2

the third param 3

the tenth param 10

the tenth param 34

the eleventh param 73

the count of params: 11 !

output all params as one string: 1 2 3 4 5 6 7 8 9 34 73 !

0

this is the first function

2

0

几个特殊字符用来处理参数
$#  传递到脚本或函数的参数个数
$*  以一个单字符串显示所有向脚本传递的参数
$$  脚本运行的当前进程ID
$!  后台运行的最后一个进程ID号
$@  与$*相同,但是使用时加引号,并在引号中返回每个参数
$-  显示shell使用的当前选项,与set命令功能相同
$?  显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误
 
输入/输出重定向:
command > file
command < file
command >> file
command << file
command < infile > outfile
command >> file 2>&1
command > /dev/null 2>&1 #将命令的输出重定向到文件/dev/null中,/dev/null文件是一个特殊的文件,写入到它的内容都会被丢弃。
 
通过‘wc -l’命令计算内容的行数;
0是标准输入(STDIN),1是标准输出(STDOUT),2是标准错误输出(STDERR)
 
Shell文件包含:
. filename # 点号(.)和文件中间有一个空格
source filename
 
#!/bin/bash
# import file ./test1.sh
. ./test1.sh
echo "import file"
if test -e ./test1.sh
then 
        echo "file is existed"
else 
        echo "file is not existed"
fi
 
运行结果:

import file
file is not existed

 

script.sh: line 174: ./test1.sh: No such file or directory


                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值