Linux-Shell
Shell编程
-vim test.sh
for file in *
do
echo "hello,"$file;
done
-chmod +x ./test.sh
添加可执行权限
1.Shell变量
通配符
2.Shell语法
变量:字符串 数字 环境变量 参数
条件判断:shell中的布尔值
命令列表
函数
内置命令
获取命令的执行结果
环境变量(与系统相关的全局变量)
$HOME 当前用户的家目录
$PATH 搜索命令列表 冒号分割
$0 Shell脚本文件名
$# 传递给脚本的参数个数
$$ shell脚本进程号(PID) 可用于生成唯一的临时文件
$PS1 命令提示符
$PS2 二级命令提示符 一般为 >
$IFS 输入域分隔符 通常为空格 制表符 换行符
参数变量 与参数相关的变量
$1,$2,...$n 第n个参数
$* 以IFS分隔的所有参数
$# 参数个数
条件判断
test 、 [ 命令,用于执行常见判断
例:检查一个文件是否存在
if test -f foo.php
then
...
fi
if [ -f foo.php ]
then
...
fi
test 字符串比较
string1 = string2
string1 != string2
-n string 字符串不为空则为真
-z string 字符串为 null(空) 则为真
test 算术比较
expression1 -eq expression2 两式相等则为真
-ne
-gt
-ge
-lt
-le
! expression
test 文件测试
-d file 如果文件是一个目录则为真
-e 文件存在则为真
-f 文件为普通文件则为真
-r 文件可读则为真
-w 文件可写则为真
-x 文件可执行则为真
-s 文件大小不为0则为真
Shell流程控制
添加判断 ===== test 或者 []
test 练习
-
写一个判断 /etc/hosts 文件是否可写的程序,如果可写,打印“yes”,否则打印 “no”
-
创建一个变量,读取用户输入,如果用户输入yes,则显示“yes”,输入no 则显示 “no”,否则显示“Sorry”
if [ -w /etc/hosts ]
then
echo "yes"
else
echo "no"
fi
exit 0
echo -n "your answer: "
read yourvar
if [ "$yourvar" = "yes" ]
then
echo "yes"
elif [ "$yourvar" = "no" ]
then
echo "no"
else
echo "Sorry"
fi
exit 0
for循环
for variable in values
do
...
done
例:
for foo in bar fud 555
do
echo $foo
done
exit 0
例:列出 f开头,.sh 结尾的文件
for file in $(ls f*.sh)
do
echo $file
done
exit 0
for i in {a..z}
do
echo $i
done
exit 0
{a..z} {1..50} 生成列表
for ((i=0;i<10;i++))
do
...
done
$(command) 用于执行command命令并获取其输出结果
case 语句
case variable in
pattern [ | pattern ] ...) statements ;;
pattern [ | pattern ] ...) statements ;;
...
esac
echo -n "Is it morning? please answer yes or no: "
read timeofday
case "$timeofday" in
yes | y | Yes | YES)
echo "Good Morning"
;;
[nN]* )
echo "Good Afternoon"
;;
* )
echo "Sorry ,answer not recognized"
echo "Please answer yes or no"
exit 1
;;
esac
exit 0
3.命令列表
AND 列表,左边statement执行成功才执行右边,全部执行成功才算成功
statement1 && statement2 && statement3 && ...
OR 列表,从左到右执行一系列命令,直到某条执行成功就算成功,后面的不再被执行
statement1 || statement2 || statement3 || ...
语句块
在某些只允许使用单个语句的地方(比如AND、OR列表中),要使用多条语句,则可以使用{}构造一个语句块
例子
get_confirm && {
ls > $tmp_file
cat $tmp_file > $tracks_file
}
4.函数
function_name () {
statements
}
function_name
1.函数调用时,脚本的位置参数($* $@ $# $1 $2 $...) 会被替换为函数的参数,函数执行完毕后,会恢复原值
2.函数中的变量默认为全局作用域,除非使用 local 关键字定义
3.通过 return 命令可以让函数返回数字值,常用于表示函数执行是否成功。如需返回字符串值,则需在函数中使用 echo,然后再函数外使用 $() 捕获;或者将字符串保存在一个变量中,函数执行完毕后读取该变量。
4.如果函数没有使用 return 指定返回值,则函数返回值为最后一条命令的退出码
捕获函数输出
foo(){echo Hi;}
result = "$(foo)"
局部变量
text="global var"
foo(){
local text="local var"
echo "funciton foo is executing"
}
echo "script starting"
echo $text
foo
echo "script ended"
echo $text
exit 0
只需要使用函数名,即可调用某个函数:
$ fname ; #执行函数
可以传递参数给函数,并由脚本进行访问:
fname arg1 arg2; # 传递参数
命令
-
break 跳出一层循环,continue 继续下一轮循环
-
: (冒号)空命令,有时用于简化条件逻辑,相当于 true 的别名。如 while : 为无限循环
-
. (点,约等于 source 外部命令),通常情况下,脚本执行一条外部命令时会启动一个新的子shell,命令在这个新环境中执行,结束后此环境被丢弃,给父shell返回退出码。但.命令可用于在当前环境中执行外部命令或脚本程序。类似 PHP 的 include()
-
echo -e 可启用反斜线转义,参考 help echo; -n 不输出换行。
-
eval ,允许执行动态生成的代码。例:
foo=10; x=foo; eval y='$'$x; echo $y -
exec 中断当前shell,执行 exec 所指定的命令
-
exit n 以退出码n结束运行。0为正常
1——125可用于自定义;126 文件不可执行;127 命令未找到; -
export 导出环境变量,后面执行的子进程均可见;
-
expr ,执行数学运算,如 x=$(expr $x + 1),也可写为 $((...)) ,具体参考 man expr
-
printf 格式化打印
-
return n 使函数返回,无参数则返回最后一条命令退出码
-
set 为shell设置参数变量;
如 set $(date); echo $2 可输出date命令的第二列(月) -
shift ,把所有参数变量左移一个位置,使 $2 变为 $1, $3 变为 $2
-
unset ,从当前环境中删除变量或函数
命令的执行
$(command) 或 command
,捕获command命令执行的字符串输出结果(不是退出码);
算术扩展
$((expression)),类似 expr命令,但比它快
尝试用shell写一个函数,该函数接收一个参数,例如4,通过递归的方式计算 4+3+2+1 的值。
function foo {
sum=0
num=$1
while test $num -ge 1
do
sum=$(($num+$sum))
num=$(($num-1))
done
}
foo 4
echo $sum
参数扩展(字符串处理)
$ file=tarball.tar.gz
$ echo ${file##*tar}
.gz
$ echo ${file#*tar}
ball.tar.gz
尽量多找,#尽量少找,找到后去掉前面找过的部分
参数扩展(字符串处理)
$ file=tarball.tar.gz
$ echo ${file%%.*}
tarball
$ echo ${file%.*}
tarball.tar
$ file=tarball.tar.gz
$ echo ${file:4:7}
all.tar
: 开始位置:截取长度
$ file=tarball.tar.gz
$ echo ${#file}
14
$ file=tarball.tar.gz
$ echo ${file:-default_file}
:- 如果file变量为空,则返回 default_file,否则返回 file 变量的值
:= 如果file变量为空,则设置file=default_file并返回,否则返回 file 变量的值
:+ 如果file变量不为空,则返回default_file
字符串长度
5.awk 文本处理工具
echo "进程ID"
echo $$
echo "文件名"
echo $0
echo "IFS分隔的参数"
echo "$*"
echo "空格分隔的参数"
echo "$@"
echo "参数个数"
echo "$#"
if [ -f "shell.sh" ]
#if test -f "shell.sh"
then
echo "shell exists"
fi
#for i in $(ls)
#for i in `ls`
#for i in {d..z}
for ((i=0;i<5;i++))
do
echo $i
done
until who | grep "$1" > /dev/null
do
sleep 60
done
echo 'a'
test="gloabal var"
foo() {
local text="local var"
echo "function foo is executing"
echo $text
}
echo "script starting"
echo $text
foo
echo "script ended"
echo $text
#计算累加
count=4
for((i=1;i<=$count;i++))
do
total=$((total+i))
done
echo "total=$total"
#字符串
filename=ni.hao.avi
echo ${filename##*.}
echo ${filename#*.}
echo ${filename%%.*}
echo ${filename:2:4}
echo ${#filename}
echo ${filename1:-$filename}
echo ${filename1:=$filename}
echo ${filename1:+$count}
#函数返回值
yes_or_no() {
echo "Is your name $* ?"
while true
do
echo -n "Enter yes or no"
read x
case "$x" in
y | yes) return 0;;
n | no ) return 1;;
* ) echo "answer yes or no"
esac
done
}
echo "your parameters are $*"
if yes_or_no "$1"
then
echo "Hi $1, nice name"
else
echo "never mind"
fi
#set $(date)
#shift
#unset $2