前言
软件工程中常使用shell脚本,进行一键化编译,因此记录相关语法。
本文以搞懂下列脚本为例:
#! /bin/bash
export PATH=$PATH:/opt/hr2-64bit-toolchain/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/hr2-64bit-toolchain/lib
ROOT_DIR=$(cd "$(dirname "$0")"; pwd)
debug_dir=$ROOT_DIR/debug_soft
if [ ! -d $debug_dir ] ;then
mkdir $debug_dir
fi
if [ $# == 0 ] ; then
GCC_FILE=boot.c
GCC_FILE1=$ROOT_DIR/boot_test/boot.c
cp $ROOT_DIR/config/strategy_vcs_soc_boot_mode_defconfig $ROOT_DIR/trunk/arch/mips64/configs/current_defconfig
elif [ $# == 1 ] ; then
GCC_FILE=$1
GCC_FILE1=`find $ROOT_DIR/device_test -name $GCC_FILE`
cp $ROOT_DIR/config/strategy_vcs_soc_kernel_mode_defconfig $ROOT_DIR/trunk/arch/mips64/configs/current_defconfig
fi
GCC_PATH=${GCC_FILE1%/*}
cd $ROOT_DIR/trunk
make current_defconfig
cd $GCC_PATH
cp $ROOT_DIR/Makefile ./
make distclean CASE_ROOT=$ROOT_DIR SW_ROOT=$ROOT_DIR/trunk
make GCC_FILE=$GCC_FILE CASE_ROOT=$ROOT_DIR SW_ROOT=$ROOT_DIR/trunk
cp ./VMEM/*.vmem $debug_dir
cp ./HEX/*.hex $debug_dir
cp ./BIN/*.bin $debug_dir
rm Makefile
一、基本语法
1. 第一行是什么
一般而言,shell中#
是作为注释语法使用,但是在shell脚本的第一行,有着特殊的作用。
#!
是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
这个指定路径只能放在文件的第一行,第一行写错或者不写时,系统会有一个默认的解释器进行解释。
常见的第一行有:
#!/bin/bash
#!/bin/sh
Linux 的 Shell 种类众多(缺省用bash),常见的有:
Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
2.export
Linux export 命令用于设置或显示环境变量。
在 shell 中执行程序时,shell 会提供一组环境变量。export 可新增,修改或删除环境变量,供后续执行的程序使用。export 的效力仅限于该次登陆操作。
定义变量时,变量名不加美元符号;使用一个定义过的变量,只要在变量名前面加美元符号即可。
export PATH=$PATH:/opt/hr2-64bit-toolchain/bin
这句解释为:在原有的环境变量PATH后追加一段“:/opt/hr2-64bit-toolchain/bin”,注意,路径之间用“:”冒号隔开。
3. 特殊变量
在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n
。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
其中$0
表示当前shell脚本的名字(相对路径),$#
表示当前命令中参数的个数;$*
以一个单字符串显示所有向脚本传递的参数;$@
以多个字符串显示每个参数。
4. 命令替换
shell扫描一遍命令行,发现了$(cmd)
结构,便将$(cmd)
中的"cmd"执行一次,得到其标准输出,再将此输出放到原来命令。
例如当前命令在/f路径执行,命令为“bash 06GIT_DIR/strategycpu/build.sh”。
ROOT_DIR=$(cd "$(dirname "$0")"; pwd)
上述命令的执行顺序:
- 用
$0
获得当前shell脚本的文件名,./06GIT_DIR/strategycpu/build.sh
- 执行
dirname ./06GIT_DIR/strategycpu/build.sh
,得到相对路径./06GIT_DIR/strategycpu
cd
切换到这个相对路径- 执行
pwd
获得绝对路径,赋值给ROOT_DIR
变量 - 结束,
ROOT_DIR=/f/06GIT_DIR/strategycpu
5. 流程控制
if
语句的结束要用fi
;
shell脚本中单中括号[]
用法同test,常用在测试条件语句的真假。
操作符 | 意义 |
---|---|
[ -f $file_var ] | 变量 $file_var 是一个正常的文件路径或文件名 (file),则返回真 |
[ -x $var ] | 变量 $var 包含的文件可执行 (execute),则返回真 |
[ -d $var ] | 变量 $var 包含的文件是目录 (directory),则返回真 |
[ -e $var ] | 变量 $var 包含的文件存在 (exist),则返回真 |
[ -c $var ] | 变量 $var 包含的文件是一个字符设备文件的路径 (character),则返回真 |
[ -b $var ] | 变量 $var 包含的文件是一个块设备文件的路径 (block),则返回真 |
[ -w $var ] | 变量 $var 包含的文件可写(write),则返回真 |
[ -r $var ] | 变量 $var 包含的文件可读 (read),则返回真 |
[ -L $var ] | 变量 $var 包含是一个符号链接 (link),则返回真 |
if [ ! -d $debug_dir ] ;then
mkdir $debug_dir
fi
这句话的意思就是:判断变量$debug_dir
是不是目录,不是的话就创建一个目录。
6. 脚本替换
#
是去掉左边(键盘上#
在 $
的左边)
%
是去掉右边(键盘上%
在$
的右边)
单一符号是最小匹配;两个符号是最大匹配.
假设:file=/dir1/dir2/dir3/my.file.txt
${file#/}:删掉第一个/ 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##/}:删掉最后一个/ 及其左边的字符串:my.file.txt
${file#.}:删掉第一个. 及其左边的字符串:file.txt
${file##.}:删掉最后一个. 及其左边的字符串:txt
${file%/}:删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/}:删掉第一个/ 及其右边的字符串:(空值)
${file%.}:删掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.}:删掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
GCC_PATH=${GCC_FILE1%/*}
7. make编译
make
是linux的命令,具体设计Makefile的语法。
总结
本示例的shell语法都比较简单,遇到不会的就百度,不需要特意笼统学习,效率太低。但是用到之后要刻意记忆,不然还是效率太低。