helloworld
#! /bin/bash
echo "hello,world"
关于hisroty命令:
HISTSIZE
是保存历史命令的条数HISTFILE
是保存历史命令的文件!N
表示执行编号为N的历史命令!!
表示执行上一条命令
$ echo $HISTSIZE
1000
$ echo $HISTFILE
/home/daniel/.bash_history
$ !2014
ls
$ !!
ls
变量
shell中的变量都是字符串类型
变量的定义
变量名和等号之间不能有空格
#! /bin/bash
my_name="daniel"
echo $my_name
echo ${my_name}
for i in $(ls /etc/); do
echo $i
done
//或者这样写
for j in `ls /bin/`; do
echo $j
done
变量名外面的花括号是可选的,推荐加上,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
使用readonly
命令可以将变量修饰为只读变量
#!/bin/bash
myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com" #报错
使用unset
命令可以删除变量,但是不能删除只读变量
#!/bin/sh
myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
变量类型
- 本地变量:本地变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问本地变量
- 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量
- 局部变量:shell函数中定义的变量
- 位置参数变量:
$0
代表脚本名,$1
到$N
代表脚本的第N个参数
bash执行脚本和source执行脚本的区别:
- 每次使用
bash
执行shell脚本时,都会开启一个bash子进程,所以访问不到我们在原来bash中定义的变量 - 但是如果我们用
source
执行脚本,由于它是在当前环境中加载脚本,所以我们能够访问到原来的变量
答案是C
关于环境变量:
export
命令显示当前系统定义的所有环境变量
echo $PATH
命令输出当前的PATH环境变量的值
修改环境变量的几种方法:
使用命令追加:export PATH=/home/uusama/mysql/bin:$PATH
修改配置文件:~/.bashrc
或~/.bash_profile
或/etc/profile
等
字符串
单引号里的任何字符都会原样输出,单引号字符串不会解引用变量
my_name="daniel"
echo "my name is \"${my_name}\"!"
echo "my name is "${my_name}"!"
echo "my name is ${my_name}!"
echo 'my name is ${my_name}!'
#输出结果
my name is "daniel"!
my name is daniel!
my name is daniel!
my name is ${my_name}!
获取字符串长度:echo "my_name length = ${#my_name}"
提取子串:
str="my name is daniel"
echo "ths substr is:${str:1:5}"
查找子串:
string="runoob is a great site"
echo `expr index "${string}" io`
数组
在 Shell 中,用圆括号来表示数组,数组元素用"空格"符号分割开
fruit=(
"apple"
"orange"
"banana"
"grape"
)
echo ${fruit[3]}
echo ${fruit[*]} #获取数组中所有元素
echo ${#fruit[*]} #获取数组中元素的个数
#输出结果
grape
apple orange banana grape
4
多行注释
echo ${fruit[3]}
:<<!
echo ${fruit[*]}
echo ${#fruit[*]}
!
echo ${fruit[3]}
:<<!
注释内容...
注释内容...
注释内容...
!
传递参数
脚本内获取参数的格式为:$n
n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数
#! /bin/bash
echo "${0}"
echo "${1}"
echo "${2}"
#运行及结果
$ ./test01.sh fuck you
./test01.sh
fuck
you
几个特殊的参数:
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与 ∗ 相同,但是使用时加引号,并在引号中返回每个参数。如 " *相同,但是使用时加引号,并在引号中返回每个参数。如" ∗相同,但是使用时加引号,并在引号中返回每个参数。如"@“用「”」括起来的情况、以"$1" “ 2 " … " 2" … " 2"…"n” 的形式输出所有参数。 |
$- | 命令行参数,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
for i in "$@"
do
echo $i
done
for j in "$*"
do
echo $j
done
#输出结果
$ ./test01.sh fuck you
fuck
you
fuck you
运算符
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。例如,两个数相加(注意使用的是反引号 ` 而不是单引号 ’
val=`expr 2 + 2`
echo "2 + 2 = $val"
算数运算符
注意表达式和运算符之间必须要有空格
#! /bin/bash
a=10
b=20
val=`expr $a + $b`
echo "$a + $b = $val"
val=`expr $a - $b`
echo "$a - $b = $val"
#乘号(*)前边必须加反斜杠(\)才能实现乘法运算
val=`expr $a \* $b`
echo "$a * $b = $val"
val=`expr $a / $b`
echo "$a / $b = $val"
val=`expr $a % $b`
echo "$a % $b = $val"
if [ $a == $b ]
then
echo "$a == $b"
fi
if [ $a != $b ]
then
echo "$a != $b"
fi
注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]
关系运算符
#! /bin/bash
a=10
b=20
if [ $a -eq $b ]
then
echo "$a equals $b"
else
echo "$a not equals $b"
fi
if [ $a -ne $b ]
then
echo "$a not equals $b"
else
echo "$a equals $b"
fi
if [ $a -gt $b ]
then
echo "$a greater than $b"
else
echo "$a not greater than $b"
fi
if [ $a -lt $b ]
then
echo "$a less than $b"
else
echo "$a not less than $b"
fi
if [ $a -ge $b ]
then
echo "$a greater equal $b"
else
echo "$a not greater equal $b"
fi
布尔运算符
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
字符串运算符
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b"
else
echo "$a != $b"
fi
if [ $a != $b ]
then
echo "$a != $b"
else
echo "$a = $b"
fi
if [ -z $a ]
then
echo "$a len = 0"
else
echo "$a len != 0"
fi
if [ -n $a ]
then
echo "$a len != 0"
else
echo "$a len = 0"
fi
if [ $a ]
then
echo "$a is not empty"
else
echo "$a is empty"
fi
文件测试运算符
file="/var/www/runoob/test.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
#! /bin/bash
echo "Input the file name"
read FILE_NAME
if [ -f "$FILE_NAME" ]; then
echo "This is a file"
elif [ -d "$FILE_NAME" ]; then
echo "This is a dir"
elif [ -l "$FILE_NAME" ]; then
echo "This is a link"
elif [ -p "$FILE_NAME" ]; then
echo "This is a pipe"
elif [ -c "$FILE_NAME" ]; then
echo "This is a charDevice"
elif [ -b "$FILE_NAME" ]; then
echo "This is a blockDevice"
elif [ -s "$FILE_NAME" ]; then
echo "This is a socket"
else
echo "This is a Unknown"
exit 0
fi
echo命令
#读入一个变量再显示
read name
echo "hello,$name"
换行与不换行:
#输出换行
echo -e "OK! \n" #-e开启转义
echo "It's a test"
#输出不换行
echo -e "OK! \c"
echo "It's a test"
显示结果定向到文件:echo "It's a test" > myfile
显示命令执行的结果:
echo `date`
如需原样输出字符串,不进行转义或取变量,请用单引号
printf命令
语法:printf format-string [arguments...]
printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等
#! /bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
test命令
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
a=10
b=20
if test $[a] -eq $[b]
then
echo "$a == $b"
else
echo "$a != $b"
fi
代码中的 [] 执行基本的算数运算
a=5
b=6
result=$[a+b] # 注意等号两边不能有空格
echo "result 为: $result"
文件测试:
cd /bin
if test -e ./not_file -o -e ./bash; then
echo "exist at least one file"
else
echo "exist no file"
fi
或者将测试条件用方括号括起来:
if [ -e ./not_file -o -e ./bash ]; then
echo "exist at least one file"
else
echo "exist no file"
fi
流程控制
if
语法:
if condition1; then
command1
elif condition2; then
command2
else
commandN
fi
例子:
a=10
b=20
if test $a -eq $b
then
echo "$a == $b"
elif test $a -gt $b
then
echo "$a > $b"
else
echo "$a < $b"
fi
//如果不用test
if [ $a -eq $b ]
then
echo "$a == $b"
elif [ $a -gt $b ]
then
echo "$a > $b"
else
echo "$a < $b"
fi
#! /bin/bash
echo "Is it morning?Please answer yes or no"
read YES_OR_NO
if [ "$YES_OR_NO" = "yes" ];then
echo "Good morning"
elif [ "$YES_OR_NO" = "no" ];then
echo "Good afternoon"
else
echo "Sorry,$YES_OR_NO not recognized.Enter yes or no"
fi
diff hash-result.txt expected-hash-result.txt
if [ $? == 0 ]; then
echo "all tests passed"
fi
for循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
例子:
for i in 1 2 3 4 5
do
echo $i
done
for s in this is a string
do
echo $s
done
#! /bin/bash
for FRUIT in apple banana pear; do
echo "I like $FRUIT"
done
#batch rename the files
for FILENAME in chap?; do
mv $FILENAME $FILENAME~;
done
#another form
for FILENAME in `ls chap?`; do
mv $FILENAME $FILENAME~;
done
while语句
语法:
while condition
do
command
done
例子:
i=0
while test $i -lt 5
do
echo $i
let i++
done
i=0
while [ $i -lt 5 ]
do
echo $i
let i++
done
i=0
while (($i<5))
do
echo $i
let i++
done
while循环还可以用来读取键盘信息:
echo "ctrl+D to exit"
echo -n "input your name:"
while read NAME
do
echo "hello,$NAME"
done
#! /bin/bash
echo "Enter password"
CNT=1
read TRY
while [ "$TRY" != "syc" -a $CNT -lt 10 ]; do
echo "Try again"
CNT=$(($CNT+1));
CNT=$[CNT+1]
read TRY
done
case语句
语法格式:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
例子:
echo "input a num:"
read num
case $num in
1) echo "num=1"
;;
2) echo "num=2"
;;
3) echo "num=3"
;;
4) echo "num=4"
;;
*) echo "others"
;;
esac
case的值甚至可以是字符串:
echo "input a site:"
read site
case "$site" in
"google") echo "www.google.com"
;;
"taobao") echo "www.taobao.com"
;;
"baidu") echo "www.baidu.com"
;;
*) echo "others"
;;
esac
#! /bin/bash
echo "Is it morning?Please answer yes or no"
read YES_OR_NO
case "$YES_OR_NO" in
y|yes|Yes|YES)
echo "Good morning";;
[nN][oO])
echo "Good afternoon";;
*)
echo "Sorry,$YES_OR_NO not recognized.Entry yes or no"
return 1;;
esac
break和continue
while true
do
echo -n "input a num between 1-5:"
read num
case $num in
1|2|3|4|5)
echo "your num is $num"
;;
*)
echo "your num is illgel"
break
;;
esac
done
函数
语法
[ function ] funname [()]{
action;
[return int;]
}
调用函数仅使用其函数名即可,实例:
function func(){
echo "this is a function"
}
func
echo $?
返回值
函数返回值在调用该函数后通过$?来获得
function adder(){
echo "this is an adder"
echo "input your first num:"
read a
echo "input your second num:"
read b
return $(($a+$b))
#return `expr $a + $b`
}
adder
echo $?
参数
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数
function funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
输入输出重定向
统计文件的行数:
wc -l myfile
#或者
wc -l < myfile
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
语法:
#在test1.sh中定义了url
source ./test1.sh
echo "the url is $url"