目录php
chmod +x ./test.sh #使脚本具备执行权限 ./test.sh #执行脚本
/bin/sh test.sh /bin/php test.php
name='bob' echo $name echo "my name id $name" echo "Hello,"$name"!" echo ${#name} #输出 4 (长度) string="你原本就很帅" echo "长度"${#string} echo ${string:1:4} #从第二个字符开始截取4个字符 echo `expr index "$string" 原本` #查找字符本或来的位置(哪一个字母先出现就计算哪一个) ##shell数组 array_name=(value0 value1 value2 value3) echo ${array_name[@]} #@获取数组全部元素 length=${#array_name[@]} #获取数组长度 echo $length lengthn=${#array_name[2]} #获取第二个元素的长度 echo $lengthn
#---------------------------------- # 这是一个注释 # author:walkingsun #---------------------------------- # 多行注释 :<<EOF 注释内容... 注释内容... 注释内容... EOF :<<! 注释内容... 注释内容... 注释内容... !
#!/bin/bash echo "Shell 传递参数实例!"; echo "执行的文件名:$0"; # $0 为执行的文件名 echo "第一个参数为:$1"; echo "第二个参数为:$2"; echo "第三个参数为:$3";
执行git
./test.sh 1 2 3
参数处理 说明 $# 传递到脚本的参数个数 $* 以一个单字符串显示全部向脚本传递的参数。 如"$*"用「"」括起来的状况、以"$1 $2 … $n"的形式输出全部参数。 $$ 脚本运行的当前进程ID号 $! 后台运行的最后一个进程的ID号 $@ 与$*相同,可是使用时加引号,并在引号中返回每一个参数。 如"$@"用「"」括起来的状况、以"$1" "$2" … "$n" 的形式输出全部参数。 $- 显示Shell使用的当前选项,与set命令功能相同。 $? 显示最后命令的退出状态。0表示没有错误,其余任何值代表有错误。 $* 与 $@ 区别: 相同点:都是引用全部参数。 不一样点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 一、二、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
## 算数运算符 运算符 说明 举例 + 加法 `expr $a + $b` 结果为 30。 - 减法 `expr $a - $b` 结果为 -10。 * 乘法 `expr $a \* $b` 结果为 200。 / 除法 `expr $b / $a` 结果为 2。 % 取余 `expr $b % $a` 结果为 0。 = 赋值 a=$b 将把变量 b 的值赋给 a。 == 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。 != 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。 ## 关系运算符 -eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。 -ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。 -gt 检测左边的数是否大于右边的,若是是,则返回 true。 [ $a -gt $b ] 返回 false。 -lt 检测左边的数是否小于右边的,若是是,则返回 true。 [ $a -lt $b ] 返回 true。 -ge 检测左边的数是否大于等于右边的,若是是,则返回 true。 [ $a -ge $b ] 返回 false。 -le 检测左边的数是否小于等于右边的,若是是,则返回 true。 [ $a -le $b ] 返回 true。 ## 布尔运算符 运算符 说明 举例 ! 非运算,表达式为 true 则返回 false,不然返回 true。 [ ! false ] 返回 true。 -o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。 -a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。 ## 逻辑运算符 && 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false || 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true ## 字符串运算符 = 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。 != 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。 -z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。 -n 检测字符串长度是否为0,不为0返回 true。 [ -n "$a" ] 返回 true。 str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。 ## 文件测试运算符 操做符 说明 举例 -b file 检测文件是不是块设备文件,若是是,则返回 true。 [ -b $file ] 返回 false。 -c file 检测文件是不是字符设备文件,若是是,则返回 true。 [ -c $file ] 返回 false。 -d file 检测文件是不是目录,若是是,则返回 true。 [ -d $file ] 返回 false。 -f file 检测文件是不是普通文件(既不是目录,也不是设备文件),若是是,则返回 true。 [ -f $file ] 返回 true。 -g file 检测文件是否设置了 SGID 位,若是是,则返回 true。 [ -g $file ] 返回 false。 -k file 检测文件是否设置了粘着位(Sticky Bit),若是是,则返回 true。 [ -k $file ] 返回 false。 -p file 检测文件是不是有名管道,若是是,则返回 true。 [ -p $file ] 返回 false。 -u file 检测文件是否设置了 SUID 位,若是是,则返回 true。 [ -u $file ] 返回 false。 -r file 检测文件是否可读,若是是,则返回 true。 [ -r $file ] 返回 true。 -w file 检测文件是否可写,若是是,则返回 true。 [ -w $file ] 返回 true。 -x file 检测文件是否可执行,若是是,则返回 true。 [ -x $file ] 返回 true。 -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。 -e file 检测文件(包括目录)是否存在,若是是,则返回 true。 [ -e $file ] 返回 true。
echo -e "OK! \n" # -e 开启转义 \n显示换行 echo -e "OK! \c" # -e 开启转义 \c 不换行 echo "It is a test" > myfile #显示结果定向到文件 echo `date` #显示命令执行结果
printf format-string [arguments...]
模仿c程序库的printf(php也是如此)github
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg printf "%-10s %-8s %-4s\n" walkingsun boy 150 # %s %c %d %f都是格式替代符 # %-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,若是不足则自动以空格填充,超过也会将内容所有显示出来。 # %-4.2f 指格式化为小数,其中.2指保留2位小数。
Shell中的 test 命令用于检查某个条件是否成立,它能够进行数值、字符和文件三个方面的测试。shell
# 数值测试 参数 说明 -eq 等于则为真 -ne 不等于则为真 -gt 大于则为真 -ge 大于等于则为真 -lt 小于则为真 -le 小于等于则为真 # 字符串测试 = 等于则为真 != 不相等则为真 -z 字符串 字符串的长度为零则为真 -n 字符串 字符串的长度不为零则为真 # 文件测试 -e 文件名 若是文件存在则为真 -r 文件名 若是文件存在且可读则为真 -w 文件名 若是文件存在且可写则为真 -x 文件名 若是文件存在且可执行则为真 -s 文件名 若是文件存在且至少有一个字符则为真 -d 文件名 若是文件存在且为目录则为真 -f 文件名 若是文件存在且为普通文件则为真 -c 文件名 若是文件存在且为字符型特殊文件则为真 -b 文件名 若是文件存在且为块特殊文件则为真
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi # 查询进程中命令行包含ssh的数量是否大于1,是返回true -c 统计数量
if ... elseif ...else ... fi数组
if condition1 then command1 elif condition2 then command2 else commandN fi
for var in item1 item2 ... itemN do command1 command2 ... commandN done
实例:bash
for loop in 1 2 3 4 5 do echo "The value is: $loop" done ## 顺序输出字符串中的字符 for str in 'This is a string' do echo $str done
while condition do command done
实例:markdown
#!/bin/bash int=1 while(( $int<=5 )) do echo $int let "int++" done
无线循环app
while : do command done 或者 while true do command done 或者 for (( ; ; ))
until 循环 until 循环执行一系列命令直至条件为 true 时中止。 until 循环与 while 循环在处理方式上恰好相反。 通常 while 循环优于 until 循环,但在某些时候—也只是极少数状况下,until 循环更加有用。 until 语法格式: until condition do command done
case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esac
实例ssh
echo '输入 1 到 4 之间的数字:' echo '你输入的数字为:' read aNum case $aNum in 1) echo '你选择了 1' ;; 2) echo '你选择了 2' ;; 3) echo '你选择了 3' ;; 4) echo '你选择了 4' ;; *) echo '你没有输入 1 到 4 之间的数字' ;; esac
break和continue (同PHP)函数
esac
须要一个esac(就是case反过来)做为结束标记,每一个case分支用右圆括号,用两个分号表示break。
[ function ] funname [()] { action; [return int;] }
实例:
funWithReturn(){ echo "这个函数会对输入的两个数字进行相加运算..." echo "输入第一个数字: " read aNum echo "输入第二个数字: " read anotherNum echo "两个数字分别为 $aNum 和 $anotherNum !" return $(($aNum+$anotherNum)) } funWithReturn echo "输入的两个数字之和为 $? !" # 传参 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}来获取参数。
注意
参数处理 说明 $# 传递到脚本的参数个数 $* 以一个单字符串显示全部向脚本传递的参数 $$ 脚本运行的当前进程ID号 $! 后台运行的最后一个进程的ID号 $@ 与$*相同,可是使用时加引号,并在引号中返回每一个参数。 $- 显示Shell使用的当前选项,与set命令功能相同。 $? 显示最后命令的退出状态。0表示没有错误,其余任何值代表有错误。
命令 说明 command > file 将输出重定向到 file。 command < file 将输入重定向到 file。 command >> file 将输出以追加的方式重定向到 file。 n > file 将文件描述符为 n 的文件重定向到 file。 n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。 n >& m 将输出文件 m 和 n 合并。 n <& m 将输入文件 m 和 n 合并。 << tag 将开始标记 tag 和结束标记 tag 之间的内容做为输入。
实例
who > users #执行 who 命令,它将命令的完整的输出重定向在用户文件中(users)
重定向深刻
command 2 > file #stderr 重定向到 file command 2 >> file #stderr 追加到 file 文件末尾 command > file 2>&1 #stdout 和 stderr 合并后重定向到 file command < file1 >file2 #stdin 和 stdout 都重定向,command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2
command << delimiter document delimiter
实例
在命令行中经过 wc -l 命令计算 Here Document 的行数: $ wc -l << EOF 欢迎来到 菜鸟教程 www.runoob.com EOF 3 # 输出结果为 3 行 $
若是但愿执行某个命令,但又不但愿在屏幕上显示输出结果,那么能够将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;若是尝试从该文件读取内容,那么什么也读不到。可是 /dev/null 文件很是有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
若是但愿屏蔽 stdout 和 stderr,能够这样写:
$ command > /dev/null 2>&1
. filename # 注意点号(.)和文件名中间有一空格 或 source filename
nohup command > myout.file 2>&1 & 0 – stdin (standard input),1 – stdout (standard output),2 – stderr (standard error) ; 2>&1是将标准错误(2)重定向到标准输出(&1),标准输出(&1)再被重定向输入到myout.file文件中。
&是指在后台运行,但当用户推出(挂起)的时候,命令自动也跟着退出
sh test.sh &
使命令永久的在后台执行
nohup COMMAND &
这里会记录典型的shell应用场景
#!/bin/sh # 清理日志 # author:walkingsun # test path=/data/app/WindBlog/runtime/logs/ #指定清理目录 timeout=`expr 30 \* 86400` #过时时间(当前设为30天) systime=`date +%s` #获取当前系统的时间 (秒为单位) files=$(ls $path) for filename in $files do fileuptime=`stat -c %Y $path$filename` #获取文件修改时间(秒) if [ $[ $systime - $fileuptime ] -gt $timeout ] then echo $path$filename echo `rm -rf $apth$filename` fi done
你能够假设每行列数相同,而且每一个字段由 ' ' 分隔.
示例:
假设 file.txt 文件内容以下: name age alice 21 ryan 30 应当输出: name alice ryan age 21 30
解答
#!/bin/bash awk '{for(i=1;i<=NF;i++){if(NR==1){data[i]=$i}else{data[i]=data[i]" "$i}}}END{for(i=1;i<=NF;i++) print data[i]}' file.txt
你能够假设一个有效的电话号码必须知足如下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)
你也能够假设每行先后没有多余的空格字符。
示例:
假设 file.txt 内容以下:
987-123-4567
123 456 7890
(123) 456-7890
你的脚本应当输出下列有效的电话号码:
987-123-4567
(123) 456-7890
#!/bin/bash awk '/^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$/{print $0}' file.txt
为了简单起见,你能够假设: words.txt只包括小写字母和 ' ' 。 每一个单词只由小写字母组成。 单词间由一个或多个空格字符分隔。 示例: 假设 words.txt 内容以下: the day is sunny the the the sunny is is 你的脚本应当输出(以词频降序排列): the 4 is 3 sunny 2 day 1
#!/bin/bash awk '{for(i=1;i<=NF;i++){a[$i]=a[$i]+1}}END{for(k in a){print k" "a[k]}}' words.txt |sort -nr -k 2