shell 入门基础知识

1. 常用shell种类

  bash、sh、zsh

2. 定义变量

  1. 左右两边不要出现空格
  eg: a=1, s=happy
  1. 如果变量有空格,则需要使用单引号双引号括起来
  eg: a="hello world "

单引号与双引号的区别:

  单引号:无法直接引用变量的值
  a="hello"  b=1 echo 'abc  $a'     输出:abc $a
  双引号:可以直接引用变量的值
  a="hello"  b=1 echo "abc  $a"    输出:abc hello
  1. 双引号支持转义,$开头的变量会被自动替换
  eg: 
  a=1
  echo $a  -->输出1
  1. 变量不需要定义也可以使用,引用未定义的变量,默认为空值
  2. 使用$var 或${var}来访问变量,得到结果一致,后者更为严谨,但$var_x和 ${var}_x 是不同的
  eg:
  a="hello" 
  echo $a_1   输出:空;因为不存在名称为a_1的变量
  echo $a _1-->hello _1(中间有空格)
  echo ${a}_1 --->hello_1

3. 系统预定义变量

   $PWD 、$USER 、$HOME、$PATH 等都是系统变量,系统启动之后变量就已经存在了

4. 数组变量

  1. 定义数组变量
    使用( )来定义数组变量,元素之间使用空格隔开,数组下标从0开始
  eg:
  a=(1 3 4 5 7)
  1. 输出数组中所有元素
  echo ${a[@]}  或  echo ${a[*]} 
  1. 输出数组对应下标位置
  echo ${a[i]}  (i为元素下标,数组下标从0开始)
  1. 输出数组最后一个元素
  echo ${a[-1]} (下标为正数,从左至右开始取元素;下标为负数,从右往左取元素)
  1. 输出数组第一个元素
  echo a  或 echo ${a[0]}
  1. 统计数组长度
  使用“#”获取数组长度  
  eg:echo ${#a[@]} 

5. 变量命名

  1. 不能使程序中的保留字:例如if, for;
  2. 只能使用数字、字母及下划线,且不能以数字开头
  3. 见名知义
  4. 统一命名规则:驼峰命名法

6. 变量类型

常用类型:数字类型、字符串类型、布尔类型

7. `` 反引号

将命令放在反引号内,相当于执行该命令

  eg :
  a=`ls`  
  echo $a -->相当于执行ls命令,将命令执行结果赋给变量a
  echo  `ls`(在所有操作系统可用),结果等于echo $(ls)(部分操作系统可用)
  array=(`ls`) ,echo ${array} --->输出数组结果集中第一个
  echo my dir is `ls`  -->  my dir is test    执行顺序:先执行ls,在执行echo操作

8. -e 转义

  echo "a\nbb"  输出:a\nbb    
  echo  -e  "a\nbb" 输出:a
                         b (-e 开启转义模式)

9. 特殊符号使用

  1. $(()) :对变量进行操作
  eg:
  a=5;b=5
  s=a+b
  echo $s  输出:a+b
  echo $((a+b))  输出:10
  1. echo $? :看上条语句的命令是成功还是失败 返回0:成功 其余不为0的值为失败
  eg:
  echo false   输出:false
  echo $?      输出:0
  ls sss       输出:ls: cannot access sss: No such file or directory
  echo $?      输出:2
  1. {1. .10} 等价于 seq 1 10,表示1到10 (中间两个连续的点)
  [root@iZ2zefahl test]# for i in {1..3};do echo $i ;done;
  1
  2
  3
  1. seq 1 3 10 表示生成一个1到10,步进为3
[root@iZ2zefahl test]# for i in `seq 1 3 10`;do echo $i ;done;
  1
  4
  7
  10

11. 数字型变量操作

  1. 计算
 [root@iZ2]# i=1;echo $i;echo $((i+1))
  1
  2

只能进行整数计算,不支持浮点数运算

 [root@iZ2zefa]# echo $((1/3))
  0

浮点数运算使用awk

 [root@iZ2zefa]# awk 'BEGIN{print(1/3)}'
  0.333333

格式化展示使用awk ,printf格式化字符串

 [root@iZ2zefahlffrq9ahi3ykd2Z test]# awk 'BEGIN{printf("%.2f\n", 1/3)}'
  0.33
  1. 更新数值
 [root@iZ2]# i=1
 [root@iZ2]# ((i=i+1));echo $i
  2

12.字符串操作

  1. ${value:offset} / ${ value: offset: length} : 从变量中提取子串
 [root@iZ2]# s="hello word"
 [root@iZ2]# echo ${s:6}
  word
 [root@iZ2]# echo ${s:6:3}
  wor
  1. ${#s} : 获取字符串长度
 [root@iZ2]# echo ${#s}
  10
  1. ${#array[*]}和${#array[@]}表示数组中元素的个数
 [root@iZ2]# a=(1 2 3 4)
 [root@iZ2]# echo ${#a[*]}
  4
 [root@iZ2]# echo ${#a[@]}
  4
  1. 掐头去尾与内容替换
    ${ value# pattern) 或 $(value## pattern) (#表示去头,## : 贪婪匹配)
 [root@iZ2]# s="hello world"
 [root@iZ2]# echo ${s#hell}
  o world
 [root@iZ2]# echo ${s#*l} //匹配到第一个l后,掐掉l以及l之前的字符串。*表示任意多个字符
  lo world
 [root@iZ2]# echo ${s##*l} //贪婪匹配,匹配到最后一个l
  d

${ value% pattern} ${ value%% pattern)( %表示去尾 , %%:贪婪匹配)

 [root@iZ2]# s="hello world"
 [root@iZ2]# echo ${s%world}
  hello
 [root@iZ2]# echo ${s%l*} //去尾,*号放后面。*表示任意多个字符
  hello wor
 [root@iZ2]# echo ${s%%l*} //贪婪匹配
  he

${ vaue/ pattern/ string} $ {value// pattern/ string} ( /表示替换 )

 [root@iZ2]# s="hello world"
 [root@iZ2]# echo ${s/hello/nohello}
  nohello world
 [root@iZ2]# echo ${s//o/ZZZ}  //所有o替换
  hellZZZ wZZZrld

#与##、%与%%、/与//的区别: 最短匹配模式VS最长匹配模式

13.判断类型

  1. 算术判断
 [ 2 –eq 2 ] 相等
 [ 2 –ne 2 ] 不等
 [ 3 –gt 1 ] 大于
 [ 3 –ge 3 ] 大于等于 [ 3 –lt 4 ] 小于
 [ 3 –le 3 ] 小于等于 
 (())也可以表示算术比较。((10>=8)) ,((10==10))
 [root@iZ2]# echo $((10>8))
  1
  1. 字符串比较
 [ str1 = str2 ] 如果两字符串相同,则结果为真
 [ str1 != str2 ] 如果两字符串不相同,则结果为真 
 [ -n "$str" ] 如果字符串不是空,则结果为真
 [ -z "$str" ] 如果字符串是空,则结果为真
 //[[ "xxxx" == x* ]] 在表达式中表示0或者多个字符
 //[[ xxx == x?? ]] 在表达式中表示单个字符
 在引用变量的时候要加双引号[ -z "$a"] 否则当a未定义时会语法报错
  1. 逻辑判断
 [ 2 -ge 1 -a 3 -ge 4 ];echo $?[ 2 -ge 1 -o 3 -ge 4 ];echo $?[[ 2 -ge 1 && 3 -ge 4 ]];echo $?//需要[[]]2层括号
 [[ 2 -ge 1 || 3 -ge 4 ]];echo $?[ ! 2 -ge 1 ];echo $?[[]][]的扩展语法,在老的sh里并不支持。推荐用[]
  1. 内置判断
 -e file 如果文件存在,则结果为真
 -d file 如果文件是一个子目录,则结果为真
 -f file 如果文件是一个普通文件,则结果为真 
 -r file 如果文件可读,则结果为真
 -s file 如果文件的长度不为0,则结果为真
 -w file 如果文件可写,则结果为真
 -x file 如果文件可执行,则结果为真

14. 逻辑判断

  1. if
    语法:
    if [ condition ] ; then …;fi
    if [ condition ] ; then …;else …;fi
    if [ condition ] ; then …;elif …;fi
 [root@iZ2z]# if [ -e test.txt ];then echo exist test file;else echo not exist test file;fi
  exist test file
 等价于:
 [root@iZ2]# [ -e test.txt ] && echo exist test file || echo not exist test file
  exist test file
  1. for 循环
 for((c1; c2; c3));
 do;
 done
 eg :for ((i=0; i <10; i++)); do echo $i; done
  1. for 遍历循环
 for f in $array[*]do
 …
 done
 eg:
 ss="aa bb cc dd" ;for x in $ss;do echo $x;done
 for x in `ls`:; do echo $x; done
 ss=(aa bb cc"sss dd") ;for x in "${ss[@]}"; do echo $x; done
  1. while 循环
 i=0;while [ $i -lt 3 ];do echo $i;((i=i+1));done
 while read line: do echo $line; done</tmp/tmp  //一行行的读取文件内容
 while read x;do echo $x;done < 1 (<输入重定向,把1文件内容循环读出输出)
 echo abc > 1  输出重定向,abc输出到1文件中(原有内容被覆盖)
 echo abc >> 1  输出重定向,abc输出到1文件中(以追加方式,原内容依旧存在)

 read a;echo $a (等待输入后原样输出)
 1234
 1234
 
 read -p "enter:" a;echo $a  (-p 提示)
 enter:1234
 1234

  1. 退出循环
 return 函数返回
 eixt 脚本进程退出
 break 退出当前循环
 continue 跳过当前的循环,进入下一次循环

15. shell操作

Bash 下还可以再重新启动一个 shell,这个 shelle 是 sub shell,原 shel 会复制自身给他。在 sub shell 中定义的变量,会随着 sub shelle 的消亡而消失

 ()子 shell 中运行
 { }当前 shel 中执行
 $$当前脚本执行的 pid
 $(ls)表示执行 ls 后的结果,与``作用一致,不过可以嵌套
 &后台执行
 $!运行在后台的最后一个作业的 PID(进程 ID)
 

 eg: 
 [root@iZ2z]#  a=abc
 [root@iZ2]# (a=1;echo $a);echo $a 
 1     //子shell中变量值
 abc
 
 sleep 10&:将当前进程放到后台运行
 按 ctrl+z  :暂停运行
 按 bg 1:恢复运行  1:任务号
 fg 1:将任务1 调回前台
 jobs: 查看运行状态   

.sh:bash 的文件

 使文件可运行:
 不添加环境变量运行
 1. 创建test.sh ;
 2. Chmod +x test.sh
 3. bash  test.sh 即可运行脚本 //这种方式会开启一个sub shell
 
 添加环境变量运行
 1. Chmod +x test.sh
 2. Vim .bash_profile   export PATH=$PATH:/home/test  (用冒号分割路径)
 3. source .bash_profile  //在当前shell中执行

16. linux 三剑客

1. grep(数据查找定位)

   用于匹配 ,grep: 查找,可用正则匹配 

 [root@iZ2]# grep "Hello" test.txt
 Hello

 grep - i:忽略大小写
 [root@iZ2]# grep -i "Hello" test.txt
 hello
 Hello
 
 | 表示管道,也就是前一个命令的输出传入下一个命令的输入
 [root@iZ2]# cat test.txt
 abc
 hello
 Hello
 cat
 kity 
 [root@iZ2]# cat test.txt | grep -i "abc"
 abc

 grep -o: 只显示匹配到的内容
 [root@iZ2]# echo abcd | grep "c"
 abcd
 [root@iZ2]# echo abcd | grep -o "c"
 c
 
 grep -io: 只显示匹配到的内容忽略大小写
 [root@iZ2zefahlffrq9ahi3ykd2Z git]# cat test.txt | grep -io "hello"
 hello
 
 正则匹配:. 任意一个字符,* 匹配一个或多个
[root@iZ2]# echo abcdefghc  | grep -o "c."
 cd
[root@iZ2]# echo abcdefghc  | grep -o "c.*"
 cdefghc

curl: 是常用的命令行工具,用来请求 Web 服务器
curl www.baidu.com/s?wd=mp3 | less : 不会铺满整个屏幕,按回车可查看下一页

搜索百度结果条数
[root@iZ2zefahlffrq9ahi3ykd2Z test]# curl -s www.baidu.com/s?wd=mp3 | grep -o "结果约[0-9,]*"   (-s:去掉curl 统计部分)
结果约2,290,000
 
[root@iZ2zefahlffrq9ahi3ykd2Z test]# curl -s www.baidu.com/s?wd=mp3 | grep -o "结果约[0-9,]*" | grep -o "[0-9,]*"
2,290,000

搜索多个内容:
1. 新建百度keyword文件,保存搜索关键字
2. [root@iZ2zefahlffrq9ahi3ykd2Z test]# while read k;do echo $k ;curl -s www.baidu.com/s?wd=$k;done < baidu.keyword | grep -o "结果约[0-9,]*" 
结果约1,760,000
结果约2,320,000
结果约2,000,000
 
echo $k不会把关键字输出,因为 | grep -o  :只显示匹配到的内容

2. awk (数据切片)

  根据定位到的数据行处理其中的分段,默认已空格为分隔符把它分隔开,然后把切开的那部分做处理,-F  :指定分割符 ,将其分割成若干个域  $0 :代表全范围   $1:代表第1个范围
 [root@iZ2]# echo "123|456|789" | awk -F '|' '{print $0}'    
 123|456|789
 [root@iZ2]# echo "123|456|789" | awk -F '|' '{print $1}'
 123
 [root@iZ2]# echo "123|456|789" | awk -F '|' '{print $2}'
 456
 [root@iZ2]# echo "123|456|789" | awk -F '|' '{print $3}'
 789

 +|_: |代表或
 [root@iZ2]# echo "123+456_789" | awk -F '+|_' '{print $2}'
 456

 last -n 5:显示5个登入用户信息
 把第一列信息打印出来
 [root@iZ2]# last -n 5 | awk '{print $1}'
 root
 root
 root
 root
 root

 cd /etc/   cat passwd  ,把第一列打印出来
 [root@iZ2]# cat passwd 
 root:x:0:0:root:/root:/bin/bash
 [root@iZ2]# cat passwd | awk -F ':' '{print $1}'
 root
 ,逗号不会被打印出来,会被替换成空格
 [root@iZ2]# cat passwd | awk -F ':' '{print $1,$7}'
 root /bin/bash
 [root@iZ2]# cat passwd | awk -F ':' '{print $1"\t"$7}'
 root    /bin/bash

 [root@iZ2]# curl -s www.baidu.com/s?wd=mp3 | grep -o "结果约[0-9,]*"  | awk -F '个|约'  '{print $0}'
 结果约2,290,000
 
 [root@iZ2]# curl -s www.baidu.com/s?wd=mp3 | grep "条评价" | awk -F 'data-from="ps_pc4">' '{print $2}'   
 49条评价</a></span></div></div></div></div>
 975条评价</a></span></div></div></div></div>
 68条评价</a></span></div></div></div></div>
 
 
 
 [root@iZ2]# curl -s www.baidu.com/s?wd=mp3 | grep "条评价" | awk -F 'data-from="ps_pc4">' '{print $2}'| awk -F '条' '{print $1}'   
 49
 975
 68

BEGIN END

 * BEGIN{ 这里面放的是执行前的语句 },多用于初始化工作
 * END {这里面放的是处理完所有的行后要执行的语句 }
 * {这里面放的是处理每一行时要执行的语句}

 [root@iZ2]# echo -e "1|2|3\n4|5|6\n7|8|9"
 1|2|3
 4|5|6
 7|8|9
 [root@iZ2]# echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{a=a+$2}END{print a}'
 15
 
 [root@iZ2]# echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{a=a+$2;print $2}END{print a}'
 2
 5
 8
 15

 awk基本结构为 : BEGIN{BEGIN操作}  {文件行处理块}  END{END操作 }
 NR:表示当前记录数,awk每读取一条记录,NR的值便加一
 [root@iZ2]#cat /etc/passwd | awk -F ':' 'BEGIN{count=0}{name[count]=$1;count++}END{for(i=0;i<NR;i++)print i,name[i]}'
 0 root
 1 bin
 2 daemon
 3 adm
 4 lp
 5 sync
 6 shutdown
 7 halt
 8 mail
 9 operator

 
 1. 查找我的ip地址
 curl -s www.baidu.com/s?wd=ip | grep "我的ip地址" | awk -F '我的ip地址|属于' '{print $2}'
 curl icanhazip.com
 
 2.获取霍格帖子点赞数  -m1:最多匹配前一行
 a=`curl -s https://testerhome.com/topics | grep -o 'href="/topics/[0-9]*"' | awk -F '/|"' '{print $4}'`;echo $a
 23753 23456 21805 23828 22467 23797 23434 23727 23779 23820 23827 23824 23796 23787 23826 23813 23825 23800 23808 23819 23784 23823 23810 23550 23781 23798 23820 23815 23814 23812 23808
 
 a=`curl -s https://testerhome.com/topics | grep -o 'href="/topics/[0-9]*"' | awk -F '/|"' '{print $4}'`;for id in $a;do url='https://testerhome.com/topics/'$id;zan=`curl -s $url | grep -o -m1 '<span>[0-9]*' | awk -F '>' '{print $2}'`;echo $zan;done
 7
 2
 9
 
 
 
 16
 74
 
 $NF: 默认取最后一个域
 [root@iZ2]# a=`curl -s https://testerhome.com/topics | grep -o 'href="/topics/[0-9]*"' | awk -F '/|"' '{print $4}'`;for id in $a;do url='https://testerhome.com/topics/'$id;zan=`curl -s $url | grep -o -m1 '<span>[0-9]*' | awk -F '>' '{print $2}'`;if [ -n "$zan" ];then echo $url '点赞人数'$zan;else echo $url '点赞人数'0;fi;done | awk -F '/' '{print $NF}'
 23753 点赞人数7
 23456 点赞人数2
 21805 点赞人数9
 23779 点赞人数0
 不输出点赞为0的:
 [root@iZ2]# a=`curl -s https://testerhome.com/topics | grep -o 'href="/topics/[0-9]*"' | awk -F '/|"' '{print $4}'`;for id in $a;do url='https://testerhome.com/topics/'$id;zan=`curl -s $url | grep -o -m1 '<span>[0-9]*' | awk -F '>' '{print $2}'`;if [ -n "$zan" ];then echo $url '点赞人数'$zan;fi;done | awk -F '/' '{print $NF}'
 23753 点赞人数7
 23456 点赞人数2
 21805 点赞人数9
 23800 点赞人数1
 23727 点赞人数80

awk 内置变量

 FS 字段分隔符
 OFS 输出数据的字段分隔符
 RS 记录分隔符
 ORS 输出字段的行分隔符
 NF 字段数
 NR 记录数

 $NF 代表最后一个字段

3. sed (数据修改)

  根据定位到的数据行修改数据,/  为分隔符,可换成其他任意分隔符
 [root@iZ2]# echo "hello cat and kity cat"  | sed 's/cat/bigcc/'
 hello bigcc and kity cat
 
 [root@iZ2]# echo "hello cat and kity cat"  | sed 's?cat?bigcc?'
 hello bigcc and kity cat
 
 g:全部替换
 [root@iZ2]# echo "hello cat and kity cat"  | sed 's/cat/bigcc/g'
 hello bigcc and kity bigcc
 
 [root@iZ2]# echo "123|456|789" | sed 's/|/+/g'
 123+456+789
 
 
 [root@iZ2]# sed 's/android/a/' baidu.keyword 
 mp4
 mp3
 ios
 a
[root@iZ2]# cat baidu.keyword 
 mp4
 mp3
 ios
 android
 源文件未替换 ?:
 sed会将要替换的文件放到一个模式空间,替换模式空间内的数据,和源文件没有关系
 
 要替换源文件内容怎么办?
 加个-i参数
 [root@iZ2zefahlffrq9ahi3ykd2Z test]# sed -i 's/android/a/' baidu.keyword 
 [root@iZ2zefahlffrq9ahi3ykd2Z test]# cat baidu.keyword 
 mp4
 mp3
 ios
 a
 
 -i.bak : 会生成一个备份文件
 [root@iZ2zefahlffrq9ahi3ykd2Z test]# sed -i.bak 's/android/s' baidu.keyword 
 [root@iZ2zefahlffrq9ahi3ykd2Z test]# cat baidu.keyword
 mp4
 mp3
 ios
 s
 [root@iZ2zefahlffrq9ahi3ykd2Z test]# cat baidu.keyword.bak
 mp4
 mp3
 ios
 Android

17.shell 注释

 单行注释:#
 多行注释:<<

18.函数传参

 1. 新建ttt.sh
 输入:
 echo "需要执行的参数是:$0";
 echo "获取到的第一个参数是:$1";
 echo "获取到的第二个参数是:$2";
 echo "获取到的参数个数是:$#";
 echo "获取到的参数是:$*";
 echo "获取到的参数(每一个参数都是一个str):$@";
 echo "获取当前进程的ID号(pid):$?";
 2. 配置环境变量
 3. 执行脚本,参数放在后面
 [root@iZ2]# ttt.sh 1 2 3 4 5
 需要执行的参数是:/home/test/ttt.sh
 获取到的第一个参数是:1
 获取到的第二个参数是:2
 获取到的参数个数是:5
 获取到的参数是:1 2 3 4 5
 获取到的参数(每一个参数都是一个str)1 2 3 4 5

$ * 与$ @ 区别

都是获取参数个数
$ * :把所有获取到的参数全部放在一个字符串里面 ,即 "1 2 3 4 5"
$@: 把每个参数当成一个字符串 ,即:"1" "2" "3" "4" "5"
记得使用”$@” ,不要直接使用$@

[root@iZ2]# ff(){ for d in $@ "$@" $* "$*"; do echo $d ; done; } ; ff 1 2 '3 "4 5" 6' 7 "8 9"
1
2
3
"4
5"
6
7
8
9
1
2
3 "4 5" 6
7
8 9
1
2
3
"4
5"
6
7
8
9
1 2 3 "4 5" 6 7 8 9

参数传参:正常只能传9个,参数大于9个时,加{}

 [root@iZ2]# cat test01.sh
 funtest(){
    echo "第1个参数为:$1"
    echo "第2个参数为:$2"
    echo "第10个参数为:$10"
    echo "第10个参数为:${10}"
    echo "第11个参数为:${11}"
    echo "参数总个数为:$#个"
 }
 funtest a b c d e f g h i j k l 
 
 [root@iZ2zefahlffrq9ahi3ykd2Z test]# test01.sh
 第1个参数为:a
 第2个参数为:b
 第10个参数为:a0
 第10个参数为:j
 第11个参数为:k
 参数总个数为:12个


 输出用户输入数据,原样输出,如果为quit,则停止
 [root@iZ2]# cat test02.sh
 while true
 do 
   read -p "please enter:" var_q
   if [ "${var_q}" = "quit" ] 
     then
       break
   else
     echo ${var_q}
   fi
 done 
 
 输入2个数,输出加减乘除  awk中引用外部变量需要使用双引号,即\"$var_a\"
 [root@iZ2]# cat test03.sh
 read -p "first num:" var_a
 read -p "sec num:" var_b
 echo "$(($var_a+$var_b))"
 echo "$(($var_a-$var_b))"
 echo "$(($var_a*$var_b))"
 echo `awk "BEGIN{print \"$var_a\"/\"$var_b\"}"`  
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值