快速入门Shell(bash)编程
学过其他编程语言的,比如说JAVA都这知道定义变量的时候,需要在变量名之前设置变量类型,比如说需要定义一个字符串:String xxx="…"
在Shell中定义变量
在shell定义变量要简单得许多,它更像是javaScript,不需要去指定变量类型,也就是说你的变量值是字符串,变量就是String类型,是数字就是int类型,不过Shell定义变量比javaScript还要简单连var都省略了
1.显式定义
#!/bin/bash
school="203"
echo "${school}
echo就是输出语句,注意在使用变量时一定要加$符号,{}可以不加,但建议还是加上,不要偷这一点懒
2.使用语句定义
#!/bin/bash
for name in LiDaiTou; do
echo "my name is ${name}"
#don't forget wiret done in the end
done
#in前面的是变量,后面是变量值,意思是将LiDaiTou这个字符串赋值给变量name,结束时千万别忘记加上'done'
3.只读变量:readonly+变量名 只读变量不可修改,unset也不能删除
#use unset to delete variable
#This is a wrong example because readonly can't be deleted
unset school
echo "${school}"
#it's right
speak="helLo"
unset speak
#can't display because the variable was deleted in the here
echo "${speak}"
小结:
输出时尽量使用双引号,单引号不能随便使用,单引号字符串中的变量无效且单引号中无法转义,因为单引号中无法出现单引号
Shell中的字符串
Shell中的字符串
1.获取字符串长度
获取字符串长度有多种,这里只介绍最简单的一种:${#变量名}
#output String's lengh in the following example str="I Love Kali"
#spaces also count as Strings,The result here is 11
echo ${#str}
# - 空格也会算作一个字符串,这里输出的结果是11
2.提取字符串:${变量名:开始下标:结束下标}
#extract Strings from first chair to sex chair output I Love
echo ${str:0:6}
# - 下标6是一个空格,最后一个下标不算,这里输出I Love,也就是说最终的输出结果是:开始下标~~结束下标-1位置的字符串
3.查找字符串中的字符处于字符串的第几个位置:expr index "${变量名}" 需要查找的字符
echo `expr index "${str}" Le`
# - 查找L或e字符,哪个字符先出现就计算哪个
Shell数组
1.定义数组:数组名=(value1 value2),每个元素用空格分开
#!/bin/bash
# This is define array
file=(/test /ShellTest. sh)
2.1获取数组中的元素
|#1.output index in the array is 0 element
echo ${file[0]}
# *- 获取数组中下标为0的元素*
2.2获取数组中的所有元素
#2.output index in the array is all element
echo ${file[a]}
# *- ${file[@]}===${file[*]}*
3.1.获取数组的长度:${#数组名[@]}
#This is acquire array's lengh,It could write like this ${#file[*]}
lengh=${#file[@]}
echo "${Lengh}"
# - 输出:2,这个数组中有2个元素
3.2获取数组中指定元素的长度:${数组名[下标]}
#acquire index in the array is o element's lenghl
lenghe=${#file[0]}
echo "${lenghe}"
# *- 输出:5,这个元素有5个字符*
Shell注释
1.单行注释:#…
2.多行注释:
:<<EOF
注释内容
。。。。。
。。。。。
EOF
或者
:<<'
注释内容
。。。。。
。。。。。
'
或者
:<<!
注释内容
。。。。。
。。。。。
!
Shell echo命令
echo用于在终端输出:echo "…"就会输出对应的字符串
1.显示转义字符
#\is a Escape symbol
echo "\"shell is a part of kali \""
# - *\是转义符号,输出:"shell is a part of kali "*
2.开启转义:echo -e “…”
echo -e "right!\n" # - *\n是换行*
3.输出内容定向至文件:echo “…” > 文件名
echo "${name} there are many more" > text
# - *如果text在当前目录下,则不用指定父级目录,否则指定完整路径*
4.获取当前时间:echo date
#display time
echo `date`
。
Shell test命令
1.数值测试
参数 | 说明 |
---|---|
–eq | 等于则为真 |
–ne | 不等于则为真 |
–gt | 大于则为真 |
–ge | 不大于则为真 |
–lt | 小于则为真 |
–le | 不小于则为真 |
#!/bin/bash
#definition 2 variable
#1.先创建两个变量。2.判断两个值得逻辑关系
num1=100
num2=200
#determine 2 values
if test $[num1]-eq $[num2]
then
echo "numl==num2"
elif test $[numl]-gt $[num2]
then
echo "numl>num2"
else
echo "numl<num2"
fi
# - *输出num1<num2*
2.字符串测试
参数 | 说明 |
---|---|
= | 等于则为真 |
!= | 不相等则为真 |
–z 字符串 | 字符串长度为0则为真 |
–z 字符串 | 字符串长度不为0则为真 |
2.1判断两个字符串值是否相等
#!/bin/bash
#definition 2 variable
# - *1.创建两个变量接收字符串。2.判断两个字符串是否相同。*
strl="my_name_is_mangfu"
str2="my_name_is_daitou"
#determine 2 values
if test ${strl}=${str2}
then
echo "these two values are equal"
else
echo "these two values are not equal"
fi
#输出:these two values are not equal
2.2判断字符串长度是否为空
#determine strings's lengh
if [-z ${strl}]
then
echo "str1==0"
else
echo "str1l=0"
fi
# - *输出:str1!=0*
3.文件测试
参数 | 说明 |
---|---|
–e 文件名 | 如果文件存在则为真 |
–r 文件名 | 如果文件存在且可读则为真 |
–w 文件名 | 如果问价 存在且可写则为真 |
–x 文件名 | 如果文件存在且可执行则为真 |
–s 文件名 | 如果文件存在且至少有一个字符则为真 |
–d 文件名 | 如果文件存在且为目录则为真 |
–f 文件名 | 如果文件在存在且为普通文件则为真 |
–c 文件名 | 如果文件存在且为字符型特殊文件则为真 |
–b 文件名 | 如果文件存在且为块特殊文件则为真 |
#!/bin/bash
# determine if the file exists
change="1s-a /etc"
if test -e./ShellT. sh then
echo "the file arealy exists"
else
${ change}
fi
# - *判断这个文件是否存在如果存在输出第一条语句,否则执行change变量中的命令。输出:/etc目录下的所有文件*
4.Shell中的与(-a)、或(-o)、非(!)
这三个逻辑操作符它们的优先级为!>-a>-o
change="1s-a /etc"
if test -e./Shellrest.sh-a./etc then
echo "the file arealy exists"
else
${change}
fi
# - *输出第一句话*
Shell流程控制
其表达式为:
if [判断条件]
then
...........(执行语句)
else或elif
...........(执行语句)
fi(记得if语句需要闭合)
注意:如果没有第二判断条件不需要加上else否则会报错
#!/bin/bash
str1="hello"
str2="hi"
if [ ${str1}==${str2} ]
then
echo "the 2 file's value the same"
else
echo "the 2 file's value the different"
fi
#值得注意的是在[ ]的首尾都必须加上空格,否则会报以下错误
#./ShellTest.sh:行4:[hello:未找到命令
Shell for循环
表达式为:
for 变量名 in value1 value2 value3.......... (每个变量值使用空格分开)
do
(执行语句)..................
done(最后记得闭合)
for out in 58 52 74 95
do
echo "${out}"
done
#每个变量值依次输出,即使是多个字符串也是一样的
输出结果↓
root@kali:~/test#./ShellTest.sh
58
52
74
95
如果你习惯了其他语言的写法,可以像这样写↓
for ((i=1;i<10;i++)); do
(执行语句).........
done
第一种写法更像是foreach,其实这两种写法还是有一些区别的,具体怎么用根据实际情况决定
Shell while语句
while语句用于不断循环语句,也可以不断从输出语句中输出语句,其语法为:
while ((条件表达式))或while [条件表达式] 。(区别在于(())内放置的是<、>、=这些符号,而[ ]内放置表达式,如-eq、-gt 、-lt)
do
(执行语句)..............
done
array=(a b c d e f g)
i=0
while((i<=${#array[@]}))
do
echo "hello"
let "i++"
done
#let命令用于计算一个或多个表达式,计算变量时不需要加$。详情查阅Bsah let命令
注意:如果使用while(())这种方式,在使用判断符号</>/=时最好不要空格,[ ]这种方式使用判断符号时需要空格
读取键盘信息
echo -n 'input your name please:'
while read name
do
echo "your name is ${name}"
break
done
read + 变量名,它的作用跟Scanner(JAVA)、scanf(C语言)一样
无限循环
表达式:
while :
do
(执行语句)............
done
while:
do
echo "hhh"
done
##########也可以写成for (( ; ; ))#########
for(( ; ; ))
do
echo "hhhh"
done
until循环
与while相反,当条件表达式为true时跳出循环
语法:
until [条件表达式]
do
(执行语句).............
done
i=0
until [!${i} -lt 10]
do
echo "${i}"
let "i++"
done
#输出:9。增长到10的时候跳出循环没有输出
case选择语句
语法:
case value(你设置的变量) in
1) 执行语句..............
;;
2) 执行语句...................
;;
...................................
;;
n) 执行语句.................
;;
esac(语句闭合,就是case反过来写)
#!/bin/bash
echo "please choose:"
read choose
case ${choose}in
1)echo "pitch on 1"
2)echo "pitch on 2"
3)echo "pitch on 3"
echo "error input"
esac
#每个选项结束时记得机上两个分号。" ;; "
还有一种简单的写法↓
#!/bin/bash
echo "please choose:"
read choose
case ${choose}in
1 | 2 | 3 )echo"pitch on ${choose}"
echo "error input"
;;
esac
#两种写法作用都是一样的
break和continue
跟其他语言一样,Shell中也是有跳转语句的,在Shell中跳转语句只能用在for、while和until中
#!/bin/bash
while:
do
echo "please choose:"
read choose
case ${choose}in
1 | 2 | 3 )echo "pitch on ${choose}"
*)echo "error input"
continue
esac
done
echo "hhhhhh"
#在这里使用continue最后一句输出语句永远不会被执行,但是用break则会执行
#break跳出所有循环
#continue跳出当前循环
函数
其语法与JavaScript有异曲同工之处
[ function ] 方法名[()]
{
(操作执行).......
[ return int ]
}
⭐:中括号内是可以不写的部分
1.无参数、不带return
function shelltest()
echo "this a function"
echo "start calling methoud"
#calling
shelltest
echo "end of the call"
#调用方法时千万别加( )否则脚本无法运行
2.无参数、带有return
function sum()
echo 'input a number:'
read num1
echo 'input a number again:'
read num2
return $(($numl+$num2))
sum
echo "the sum is $?"
#所有函数在使用前必须先定义,使用$?来接收函数,但$?仅对上一条指令负责
输出结果↓
input a number:
2
input a number again:
5
the sum is 7
3.带参数传递
function param()
echo "this is first param $1"
echo "this is tenth param ${10}"
echo "this is tenth param $10"
echo "this is tenth param $12"
echo "a total of $# param"
param 1 3 5 2 8 1 7 9 45 87 22 31
⭐:函数中的$n就是调用第n个参数,比如说调用第一个参数就是 1 , 调 用 第 十 个 参 数 是 1,调用第十个参数是 1,调用第十个参数是{10},在Shell中当n>=10时在调用时需要加上{ }
this is first param 1
this is tenth param 87
this is tenth param 10
this is tenth param 12
a total of 12 param
$#是获取参数个数,还有一些特殊参数见下图
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以单字符串显示所有像脚本传递的参数 |
$$ | 脚本运行的当前进程ID |
$! | 后台运行的最后一个进程ID |
$@ | 与$*相同,但在使用时加单引号,并在引号中返回每个参数 |
$- | 显示Shell使用的当前选项,与set命令功能相同 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表示有错误 |
输入/输出重定向
在渗透实战中重定向操作是我们常用的
命令 | 说明 |
---|---|
指令 > file | 将输出重定向到指定文件 |
指令 < file | 将输入重定向到指定文件 |
指令 >> file | 将输入以追加的方式重定向到指定文件 |
n > file | 将文件描述为n的文件重定向到指定文件 |
n >> file | 将文件描述为n的文件以追加方式重定向到指定文件 |
n >& m | 将输出文件m和n合并 |
n <& m | 将输入文件m和n合并 |
<<tag | 将开始标记tag和结束标记tag之间的内容作为输入 |
这个操作其实并不难,通常我们只用得到前面三个
1.将输出定向到指定文件,>指定文件名,当我我们需要查看某信息时就可以打开这个文件查看
2.将文件内的内容定向到终端,就是将文件内预制的指令读取出来
3.追加输出,文件内原有的内容不会被替换
文件包含
和其他语言类似,Shell也可以包含外部文件,简单的来说就是把一些公用的方法、代码放置在一个文件中,在需要使用的时候方便另一个文件调用
1.新创建一个脚本文件:touch 文件名
2.在新脚本写入代码
#!/bin/bash
name="hhhh"
echo ${name}
3.在另一个脚本中调用
#!/bin/bash
# start
. ./newfile.sh
echo "name is ${ name}"
#调用文件格式为. 文件名(.和文件名之间有一个空格)
4.运行
root@kali:~/test#./ShellTest.sh
hhhh
name is hhhh
被调用文件不需要添加可执行权限,只要调用的文件有执行权限就行了