编程语言shell

1:基本知识

主要介绍shell语法

参数$符号

$0 :这个程式的执行名字
$n :这个程式的第n个参数值,n=1..9
$* :返回所有参数字符串,此选项参数可超过9个。
$@ :跟$*类似,参数数组
$# :参数个数,不包含脚本
$$ :这个程式的PID(脚本运行的当前进程ID号)
$! :执行上一个背景指令的PID(后台运行的最后一个进程的进程ID号)
$? :执行上一个指令的返回值 ,0:正确,其他值:有错误
$- :显示shell使用的当前选项,与set命令功能相同

反单引号

单引号:使任何字符失去意义:普通字符,特殊字符:\,反引号`,通配符。。。;
如何 引用变量:但通过单引号嵌套可使用变量:如;'he is '${name}''
双引号:可以引用变量,使用转义\,
反单引号:代表引用命令,作用与$(xxx)作用相同,
$(cmd1;cmd2;...) 与 `cmd1;cmd2;...`起到同样作用;都是命令替换。

判断、条件组合、嵌套

基本用法

文件测试

-e/-s: 文件存在/存在且size不为0为真;

-r/-w/-x: 权限判断,前提:文件存

-z (长度为0真); -n(长度非0真)

-d/-f: 存在且为目录/文件为真;

-c/-b: 文件存在且为字符/块设备为真

比较

比较符号:2类:

A类: -eq, -ne, -gt, -ge, -lt, -le

B类: =, ==, !=, >, >=, <, <=

数字比较:  [A类] 或 [[A类]] 或 ((B类))

字符串比较: [B类] 或 [[B类]]

注意:

1:[[]] 中触发模式匹配,结合=~,模式(如*hello*)不能在引号内

2:[]中<,>主要转义:\<, \>

3: 在判断、比较中 [[]] 更通用

s1=abc    s2=abc*

if [ "${s1}" =(或==或!=) “${s2}” ] 或

if [ "${s1}" =(或==或!=) ${s2} ] // []中s2有无引号均为普通字符串

if [[ "${s1}" == ${s2} ]] // true,[[]]中s2不加引号为模式,否则为字串

if [ "${s1}" \> “${s2}” ] 或 if [[ "${s1}" > ${s2} ]] // false

逻辑组合

只能用在 []: -a, -o, !

只能用在 [[]]: &&, ||

统一规则:字符串统一用引号包括,使用=或==,数字统一不用引号,使用-eq等判断;

条件嵌套(子条件组合)

#!/bin/bash
t=$(date +%s)
touch "${t}.bz2"
n=0
path="."
for f in $path/*;do
    if [[ ("$f" == *${t}*) || ("$n" -lt "3" && "$f" == ${t}*) ]] && [[ "${f: -4}" == ".bz2" ]]; then
        echo "find $f"
    fi
done

# or

for f in $path/*;do
    if [[ ("$f" == *${t}*) || ("$n" -lt "3" && "$f" == ${t}*) && ("${f: -4}" == ".bz2") ]]; then
        echo "find $f"
    fi
done
rm -f "${t}.bz2"

注意:
1: 上面例子中有模式匹配、条件嵌套,条件嵌套必须用小括号()
2: ||和&&可以在[[]]内部,也可以在外部链接[[]]

通配符、转义符、-e

=~  模糊匹配操作符

判断左侧的参数是否能被右侧pattern匹配,匹配返回真(0),否则返回假(1)

用法:[[ $str =~ pattern ]] 必须在 [[]] 内才触发模式匹配

模糊匹配语法

通配符

^       匹配行首

$       匹配行尾

.       任意单个字符 (有些命令工具里 ? 表示任意单个 )

*       匹配0或多个前面单个字符

[]      匹配字符集内任意一个字符,如:[xyz]、[0-9]

[^]     匹配字符集内任意一个字符,如:[^xyz]、[^0-9]

a\{1\}        匹配前面的 (a) 字符出现 (1) 次。若用 egrep 可以去掉斜线。

a\{1,\}       匹配前面的 (a) 字符至少出现 (1) 次。若用 egrep 可以去掉斜线。

a\{,2\}       匹配前面的 (a) 字符最多出现 (2) 次。若用 egrep 可以去掉斜线。

a\{1,2\}      匹配前面的 (a) 字符出现 (1~2) 次。若用 egrep 可以去掉斜线。

[:alnum:]     匹配任意一个字母或数字,类似:[:alpha:]、[:digit:] 、[:lower:]、[:upper:]

\    转义,屏蔽元字符的特殊意义

a{abc,xyz,123}b  匹配换括号里任意一个子串

-e 开启转义

shell转义同c语言,不过需要显示开启:如:echo -e "\n" 打印换行

2:变量与函数

变量与作用域

作用域:shell所有变量(包含函数里的)默认都是全局;仅在函数里可以使用local定义局部变量

引用:正确方式${var},这种方式可以使用更多场景:如: b="${a}_pch"

注意:变量值 含空格 必须用引号(单或双引号)

定义局部变量(一般用在函数里):local val=9

declare声明类型变量

  1. declare [+/-] [选项] 变量名

+ : 取消变量类型的属性

-  :给变量设定类型属性

  1. 选项类型:

a : 将变量声明为数组型

i : 将变量声明为整数型

x :  将变量声明为环境变量

r : 将变量声明为只读变量

p : 显示指定变量的被声明的类型

变量判空与处理

${var:-string} var不空用var,否则用string,string可以是:常量、变量、cmd输出;

${var:=string} var不空用var,否则用string,同时将var赋值string;

${var:+string} var为空用var,否则用string,不改变var值;

${var:?string} var不空用var,否则将string打印到标准错误输出,终止程序;

函数-参数-return-exit-返回值

函数定义、参数:

[function ]Hello() //function可不加
{
    echo "param num=$#, $2"
    local num=0 //函数里变量默认也是全局的,这里用local定义局部变量
}

函数调用不加(),后面跟参数:Hello zhangsan //参数可以不用加引号
1:函数体 不可空;且 只返回数字,要返回子串可用变量接收,如右:
2:$0仍表示脚本名,$n(n>0) 表示函数的实际参数, $# 表示参数个数(不含函数名)

函数返回值及使用(均当作字符串):

使用echo 返回:
function test() {
    name=$1
    echo "123213"
}
ret=$(test "aaaa")

return、exit及返回值捕获
1: return 仅在函数里使用、仅返回0-255的数字(超255从0开始)、return后语句不执行
   或者: source b.sh 用source 方式执行代码,b.sh 脚本中可以在非函数中使用 return 数值
2: exit 退出整个脚本
3: 函数、shell命令、shell脚本返回值均可用 $? 捕获

3:命令组管道

一行条命

分隔符

格 式

作 用

cmd1 ; cmd2

顺序执行:cmd1,cmd2...;无论cmd1成功失败,cmd2都执行

&&

cmd1 && cmd2

cmd1成功($?=0),cmd2才执行;cmd1失败($?≠0)cmd2不执行

||

cmd1 || cmd2

cmd1失败($?≠0),cmd2才执行;cmd1成功($?=0)cmd2不执行

命令组命令组返回值

()

1:命令组:(cmd1;cmd2),开新shell;()内变量外部不可见;

2:值替换:$(cmd),将输出放到原位置

(())

1:整数扩展:+、-、*、/、%,以及数字逻辑判断,不支持浮点;sum=$(($sum+4)) 不能有空格;

2:C语言扩展:$((exp)),exp必须符合C语言规范,甚至三目运算。

{}

1:命令组:{ cmd1;cmd2;},不开新shell,而是创建函数,内部变量外部可见;格式:cmd1与左{有空格,最cmd后有分号;

2:名称扩展:ls {ex{1..3},ex4}.sh,ls {ex[1-3],ex4}.sh

管道|

如下命令:echo $xxx | hi 中hi 相当于一个进程在管理内执行,exit只退出当前hi函数
#!/bin/sh 
hi()
{
    read filename
    echo $filename 
    exit 1 //仅退出函数,和return 1一样
}
echo $file | hi //hi函数在管理执行的,相当于一个进程

4:数字与字符串

数字运算

let运算符:

let i++; let ++i; let i+=j; let i*=9

let x=7/3   //取整

let x=7%3  // 取余单、双引号均可

类型转换: shell自动转换,但类型不对报错

字符串->数字:age="100";let iage=${age}

字符串操作

变量:str="123abc123"
取长度:echo "${#str}"
左截取:${string:position:length} :从字符串 string 的 position 位置截取 length 个字符串,length 可选
echo ${str:3:3}         // 输出:abc
echo "${str:0:${#str}-3}"  // 输出:123abc
右截取:${string:空格 -lenth} 截取字符串 string 的后 lenth 个位置
echo ${str: -4}      // 输出:c123
echo ${str:0-4}      // 输出:c123,空格可以看成 0
echo ${str:1-4}      // 输出:123,1-4就相当于 空格-3 或者说 0-3
从左开始匹配删除:# 和 ##,${string#pattern},${string##pattern}, #(尽可能少删字符) 和 ##(贪婪模式:尽可能多删字符)
其中 pattern 可以是一个正则表达式
echo "${str##*1}"    // 输出:23
echo "${str#*1}"     // 输出:23abc123
echo "${str##1}"     // 输出:23abc123
echo "${str#1}"      // 输出:23abc123
从右开始匹配删除 % 和 %%
echo ${str%%2*3}    // 输出:1
echo ${str%2*3}      // 输出:123abc1
普通替换: ${string/pattern /new},${string//pattern /new}  其中: /表示只替换一个,// 表示全部替换
echo "${str/123/r}"    // 输出:rabc123
echo "${str//123/r}"    // 输出:rabcr
echo "${str/3*1/r}"     // 输出:12r23, 3*1为正则表达式,中间*表示任意多字符
含有转义字符替(贪婪模式):
s=abc/123/abc
echo ${s/*\//}          // 输出:abc
前后缀替换: ${string/#pattern/new}, ${string/%pattern/new}   其中:#表示匹配开头子串,%匹配结尾子串,他们只替换一个匹配的项
echo "${str/#123/r}"    // 输出:rabc123
echo "${str/%123/r}"    // 输出:123abcr
echo "${str/%c*123/r}"  // 输出:123abr   如果替换中有*,则进行贪婪匹配,并替换第一个最大匹配项。

5:数组或列表

数组定义
list=("value1" "value2" "value3")
vec="ni hao xiao ming" // 字符串数组,${vec},返回里面单词列表
数组操作
${list[n]}         //n从0开始,第一个也可是:${list},越界返回空
echo ${!list[*]} //打印所有下标
echo ${list[*]}  //打印所有元素值:连接成字符串
${list[@]}        //所有元素,返回列表(数组)
list=("${list[@]}" "value4") //增加一个元素
${#list[@]}或${#list[*]}      //长度
${#list[0]}        //元素长度
   unset list[0]     // 删除0号元素
   unset list         // 删除数组
遍历数组
for i in ${list[*]}
do
xxx
done

6:字典

定义字典
declare -A dic
dic=([key1]="value1" [...Kv对空格分开]") //key也可以带引号
dic=( // 可以分行
["k1"]="v1"\
["k2"]="v2"\
)

操作
echo ${dic[key]} //返回k-v对,key可带引号
echo ${!dic[*]}  //打印所有key
echo ${dic[*]}   //打印所有value
dic["k3"]="v3"   // 添加元素

遍历key值
for key in $(echo ${!dic[*]})
do
    echo "$key : ${dic[$key]}"
done

7:流程控制

循环与分支均可嵌套,循环中用break, continue,同C语言

for循环与for...in

分号问题: do在for同一行必须加,否则可选
命令行循环:for((a=1;a<=100000;a++));do lua stat.lua;done //双()里空格可选
其他形式:
for i in f1 f2 f3        // 字符串枚举
for file in /proc/*      // 目录文件枚举
for file in $(ls *.sh)    // 文件列表枚举
for i in `ls`           // 遍历文件夹
for i in {1..10}        // 数字序列
for i in $(seq 1 10)     // 数字序列
for i in `seq 0 4`

while

分号问题: do在while同一行必须加,否则可选
条件两边无空格,>0:永远循环;或 i<j形式;
命令行: while ((条件));do xxx done //while与(之间必须有空格,双()里空格可选
其他形式:
while [[ $num -lt 2 ]];do xxx done    //双[]与里面字符及内部操作必须加空格
while read n;do xxx done

until

特点: 条件假时执行
i=0
until [[ "$i" -gt 5 ]] //大于5
do
    let "square=i*i"
    let "i++"
done

if、elfi、else、fi

分号问题:条件后必须有分号
if (($i<5));then // if 后 有空格,不过最好用 -lt; (())内可没有空格
    xxxx
fi
多个if-elfif-else
if [ $1x == "ab"x ]; then
    xxx
elif [ $1x == "cd"x ]; then
    xxx
else
    xxx
fi
if-else也可以嵌套

case...in

多匹配,双分号

read n
case $n in
1)
    echo "get num 1" ;; //换行自定义对齐,每个匹配后都需有双分号
4|5)
    echo 'get num 4 or 5' ;; // 可以不换行
*)
    echo "any num else 1";;
esac

select...in

作用:显示可选择编号的菜单,用户选择序号,赋值给变量,并执行响应的逻辑,常和case联合使用,示例如下:

select color in "red" "blue" "green"                
do
    if [[ "" == "$color" ]];then
        break // break可以退出select...in交互,否则一直循环
    fi
    case "$color" in
        "red")
            xxx
        break
        ;;
        "blue")
            echo "$color"
        break
        ;;
        "green")
            echo "$color"
        break
        ;;
        "*")
            echo "$color"
        break
        ;;
    esac
done

运行后显示:

若用户选择不在菜单内,color赋空值。

8: 常见工具命令

1: chown (一般只能root管理执行)
    chown x:x /tmp 只改变 /tmp 这一层文件夹归属和群组,下面的字目录和文件,不变,
    chmod -R x;x /tmp 递归改变 /tmp 及下面 文件夹和文件的归属和群组
2: chmod (一般只能root管理执行)
    chmod 777 /tmp 只改变 /tmp 这一层文件夹权限属性,下面的字目录和文件,不变,
    chmod -R 777 /tmp 递归改变 /tmp 及下面 文件夹和文件的权限属性

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值