一文看懂Linux Shell编程

解释性语言语言:python/shell/ruby等脚本语言
编译性语言:C/C++


作为一种Shell编程习惯

应该总是把变量取值放在双引号之中,如[ “$VAR” = ‘abc’ ]


常识

1.脚本文件以 #! 开头,用于指定命令解释器
2.如何执行脚本?
(1)给脚本添加可执行权限:chmod a+x example.sh
(2)执行方式:

./example.sh
. example.sh
source example.sh
/bin/sh example.sh
/bin/bash example.sh

内建命令 (不需要解释器就能执行的命令)

用户在命令行输入命令后,一般情况下Shell会fork并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程。

  1. 以前学过cd/alias/umask/exit等都是内建命令
  2. 凡是用which命令[查不到]程序文件所在位置的命令都是内建命令
  3. 内建命令没有单独的man手册,查看内建命令应该执行man bash-builtins
  4. 内建命令虽然不创建新的进程,但是也有Exit Status,通常用0表示成功/非零表示失败,Exit Status可以用特殊变量$?读出

小括弧()的特殊用法

在这里插入图片描述

区别&&原因

加() 不加()
区别 PWD不改变 PWD改变
类比于 直接执行./test.sh, PWD不变 source ./test.sh, PWD改变
原因 会fork一个子Shell执行小括弧中的命令 直接在交互式Shell下执行,改变交互式Shell的PWD

变量

1.本地变量

2.环境变量

echo $PATH
env|grep $PATH

(1)创建 / 查看环境变量
1.创建本地变量:VAR=hello
2.使用export关键字,将本地变量导出编程环境变量:export VAR
3.查看将VAR定义成环境变量:env | grep VAR
补充:grep
grep VAR # 查询结果是VAR字符串本身
grep $VAR # 查看结果是VAR变量的真实值,即hello
(2)删除变量unset
unset 变量名 # 将已经定义的环境变量/本地变量删除


命令代换

显示命令本来的作用
实现方法由两种

  1. 命令由 `反引号 (英文输入法模式下,Esc下面的按键)括起来
  2. 命令由 $() 括起来

算术运算 + - * /

echo  $(($VAR+30))
echo  $((VAR+30))

echo  $[$VAR+30]
echo  $[VAR+30]  # 最常用
echo  $[2#10+30]      # 2进制的10 + 10进制的30
echo  $[7#11+5#30]    # 7进制的11 + 5进制的30

转义字符 \

创建文件$和$test
	touch \$ \$test
创建文件-----abc
	touch ./-----abc

单双引号

单引号 双引号
单纯打印字符串,没有区别
防止通配符扩展
不允许变量扩展 允许变量扩展 (打印变量的值)

一文看懂Linux Shell编程_第1张图片

条件测试: test 或 [ ]

命令 test[ ] 可以测试一个条件是否成立:如果测试结果为真,则该命令的Exit Status为0;如果测试结果为假,则命令的Exit Status为1(注意与C语言的逻辑表示正好相反)。

语法 含义
[ -d DIR ] 如果DIR存在并且是一个目录,返回真
[ -f FILE ] 如果FILE存在并且是一个普通文件,返回真
[ -z STRING ] -zero,如果STRING的长度为0,返回真;STRING建议加“ ”
[ -n STRING ] -not zero,如果STRING的长度为非0,返回真;STRING建议加“ ”
[ STRING1 = STRING2 ] 如果STRING1与STRING2相等,返回真
[ STRING1 != STRING2 ] 如果STRING1与STRING2不相等,返回真
[ ARG1 OP ARG2 ] ARG1和ARG2应该是整数 或 取值为整数的变量OP是-eq(等于) -ne(不等于) -lt(小于) -le(小于等于) -gt(大于) -ge(大于等于)之中的一个
语法 [ 与 / 或 / 非 ]逻辑运算
[ ! EXPR] EXPR可以是上表中的任意一种测试条件,!表示“逻辑非”
[ EXPR1 -a EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示“逻辑与”
[ EXPR1 -o EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示“逻辑或”

分支

(1) if/then/elif/then/else/fi

一文看懂Linux Shell编程_第2张图片
注解:最后一句 if :;then …中的冒号:,该冒号:表示的含义是true
一文看懂Linux Shell编程_第3张图片
注解:read YES_OR_NO,表示从键盘中读取值,存放在变量YES_OR_NO中,其中read相当于C语言中的gets

(2) case/esac

Shell脚本的case
不存在switch,只有case…esac
可以匹配字符串和Wildcard
每个匹配分支可以有若干条命令,末尾必须以;;结束

一文看懂Linux Shell编程_第4张图片

循环

(1) for/do/done

Shell脚本中的for循环结构,类似于foreach循环,是循环遍历,例如:

  1. 将ls命令执行结果,一次给变量filename;然后做do…done中间夹的操作
    一文看懂Linux Shell编程_第5张图片
  2. 将chap?更名为chap?~
    在这里插入图片描述

(2) while/do/done

尝试输入密码3次
一文看懂Linux Shell编程_第6张图片

break和continue

break continue
break[n]可以指定跳出几层循环,用法不同C语言 continue跳过本次循环,用法同C语言
不常用 常用

位置参数和特殊变量

符号 含义
$? 上一条命令的Exit Status
$$ 当前进程号
$0 相当于C语言main函数的argv[0]
$1 $2 … 相当于C语言main函数的argv[1] argv[2] …
$# 相当于C语言函数的argc-1,表示参数的数量,注意这里的#不表示注释
$@ 表示参数列表"$1" “$2” …,例如可以在for循环中的in后面
$* 表示参数列表"$1" “$2” …,例如可以在for循环中的in后面

补充:shift
位置参数可以用shift命令左移。比如shift 3表示原来的$1,$2,$3丢弃;$4变成$1,$5变成$2,$6变成$3,以此类推。


Shell中的函数

  1. 一次性创建多个目录,各目录名通过命令行参数传入,如./create_dir dir1 dir2 dir3 dir4 表示创建目录dir1 dir2 dir3 dir4。
  2. 脚本逐个测试各个目录是否存在
    • 如果不存在,则创建
    • 如果存在,则什么也不干
#! /bin/sh 

is_directory()  #  判断目录$1是否存在,函数返回值是1或0
{
  DIR_NAME=$1  
  if [ ! -d $DIR_NAME ];then
    return 1;
  else
    return 0;
  fi
}

for DIR in "$@";do 
  if is_directory "$DIR";then  # 调用函数is_directory判断DIR存在
    :
  else 
    echo "$DIR doesn't exist,Creating it now ... "
    mkdir "$DIR"
    if [ $? == 0 ];then 
      :
    else 
      echo -e "create dir error\n"
      exit 1
    fi 
  fi 
done

Shell脚本调试

选项 含义
-n 读一遍脚本中的命令,但是不执行,用于检查脚本中的语法错误
-v 一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
-x 提供跟踪执行信息,将执行的每一条命令和结果依次打印出来

三种常见的使用方法

  1. 在命令行提供参数,如:
    在这里插入图片描述

  2. 在脚本开头提供参数,如:
    一文看懂Linux Shell编程_第7张图片

  3. 在脚本中使用set x命令启用/禁用参数,可以选定区域进行调试
    看下面的例子的执行情况,很显然:
    (1) 夹在set -x和set +x中间的语句 ⇒ 既会显示原句,又能显示结果
    (2) 不夹在set -x和set +x中间的语句 ⇒ 不显示原句,只显示结果

一文看懂Linux Shell编程_第8张图片

你可能感兴趣的:(Linux命令,/,shell编程)