Linux之shell&Makefile


最简单的shell

#!/bin/bash
echo "Hello World"

Shell 变量

注意: 变量的“=”前后不能有空格

#!/bin/bash
myStr="hello world"
myNum=100

访问变量

当想要访问变量的时候,需要使用$,否则输出的将是纯文本内容

#!/bin/bash
myStr="hello world"
myNum=100
echo $myStr
echo myNum

shell 运算

表达式

expr命令为Linux中的命令,一般用于整数值计算,但也可用于字符串操作。

  • 格式
    • expr argument operator argument
  • 参数说明
    • argument:为第一个参数
    • operator:为操作运算符
    • argument:为第二个参数

运算符号

运算符 含义
+ 加法运算
- 减法运算
* 乘法运算
/ 除法运算
% 求余
== 相等
= 赋值
!= 不相等
-a
-o
!
-eq 两个数相等返回true
-ne 两个数不相等返回true
-gt 左侧数大于右侧数返回true
-It 左侧数小于右侧数返回true
-ge 左侧数大于等于右侧数返回true
-le 左侧数小于等于右侧数返回true
= 两个字符串相等返回true
!= 两个字符串不相等返回true
-z 字符串长度为0返回true
-n 字符串长度不为0返回true
-d file 检测文件是否是目录,如果是,则返回 true
-r file 检测文件是否可读,如果是,则返回 true
-w file 检测文件是否可写,如果是,则返回 true
-x file 检测文件是否可执行,如果是,则返回 true
-s file 检测文件是否为空(文件大小是否大于0,不为空返回 true
-e file 检测文件(包括目录)是否存在,如果是,则返回 true

一些例子

#!/bin/sh
a=10
b=20
if [ $a -eq $b ]
then
   echo "true"
else
   echo "false"
fi

if [ $a -ne $b ]
then
   echo "true"
else
   echo "false"
fi

if [ $a -gt $b ]
then
   echo "true"
else
   echo "false"
fi

if [ $a -lt $b ]
then
   echo "true"
else
   echo "false"
fi

if [ $a -ge $b ]
then
   echo "true"
else
   echo "false"
fi

if [ $a -le $b ]
then
   echo "true"
else
   echo "false"
fi

获取字符串长度

mtext3="hello world"
echo ${#mtext3}  #输出字符串长度
echo ${mtext3:1:4}  #截取字符串 1到4

输出

11
ello

变量计算

a=3
b=5
val=`expr $a / $b`
echo "Total value : $val"

val=`expr $a % $b`
echo "Total value : $val"

if [ $a == $b ]
then
   echo "a is equal to b"
fi
if [ $a != $b ]
then
   echo "a is not equal to b"
fi

数组计算

#!/bin/sh
array=(1 2 3 4 5)  #定义数组
array2=(aa bb cc dd ee)  #定义数组
value=${array[3]}  #找到某一个下标的数,然后赋值
echo $value  #打印
value2=${array2[3]}  #找到某一个下标的数,然后赋值
echo $value2  #打印
length=${#array[*]}  #获取数组长度
echo $length

判断语句

  • if
  • if-else
  • if-elseif
#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
   echo "true"
fi


if [ $a == $b ]
then
   echo "true"
else
   echo "false"
fi


if [ $a == $b ]
then
   echo "a is equal to b"
elif [ $a -gt $b ]
then
   echo "a is greater than b"
elif [ $a -lt $b ]
then
   echo "a is less than b"
else
   echo "None of the condition met"
fi

判断两个变量的值是否相等:test $[Val1] -eq $[Val]

if test $[a] -eq $[b]
then
    echo "a 等于 b"
else
    echo "a 不等于 b"
fi

for 循环

#!/bin/sh

for i in {1..5}
do
    echo $i
done


for i in 5 6 7 8 9
do
    echo $i
done


for FILE in $HOME/.bash*
do
   echo $FILE
done

函数

没有返回值函数

#!/bin/sh

sysout(){
    echo "hello world"
}

sysout

有返回值函数

test(){

    aNum=3
    anotherNum=5
    return $(($aNum+$anotherNum))
}
test
result=$?
echo $result

定义传递参数的函数

#!/bin/sh

test(){
    echo $1  #接收第一个参数
    echo $2  #接收第二个参数
    echo $3  #接收第三个参数
    echo $#  #接收到参数的个数
    echo $*  #接收到的所有参数
}

test aa bb cc

shell 颜色输出

利用echo 或者printf 可以输出带颜色的shell终端字体

例子

echo -e "\033[43;35m  Hello World \033[0m \n" 

printf "\033[44;36m  Hello World \033[0m \n" 

格式

echo -e "\003[背景颜色;文字颜色;显示方式m字符串\003[0m"
  • -e 是命令 echo 的一个可选项,它用于激活特殊字符的解析器,可以转义反斜杠字符;
  • \033 引导非常规字符序列;
  • m 意味着设置属性然后结束非常规字符序列,显示的字符串之前有一个 m ;

显示方式具体内容:

显示方式 含义
0 关闭所有属性
1 设置高亮
4 下划线
5 闪烁
7 反显
8 消隐

颜色

文字颜色 背景颜色 颜色
30 40 黑色
31 41 红色
32 42 绿色
33 43 黄色
34 44 蓝色
35 45 紫红色
36 46 青蓝色
37 47 白色

Makefile

patsubst(替换通配符)

原型:

$(patsubst 原模式, 目标模式, 文件列表)$(patsubst pattern, replacement,text)

功能:

查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符)

返回:
**函数返回被替换过后的字符串。

**例子:

(patsubst %.c,%.o,x.c.c bar.c)

把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”

拓展-变量替换引用

对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。格式为$(VAR:A=B)(或者${VAR:A=B}),意思是,替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“A”字符不进行替换。例如:

foo := a.o b.o c.o
bar := $(foo:.o=.c)

在这个定义中,变量“bar”的值就为“a.c b.c c.c”。使用变量的替换引用将变量“foo”以空格分开的值中的所有的字的尾字符“o”替换为“c”,其他部分不变。如果在变量“foo”中如果存在“o.o”时,那么变量“bar”的值为“a.c b.c c.c o.c”而不是“a.c b.c c.c c.c”。

wildcard(扩展通配符)

原型:

SRC = $(wildcard *.c ./foo/*.c)

功能:

搜索当前目录及./foo/下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值给SRC.当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foor/bar.c。

notdir(去除路径)

原型:

SRC = $(notdir wildcard)

功能:

去除所有的目录信息,SRC里的文件名列表将只有文件名。

addprefix(添加固定前缀)

原型:

$(addprefix fixstring,string1 string2 ...)

功能:

其中,fixstring表示任意要添加的固定前缀,在逗号的后面可以是一个或多个要添加前缀的子字符串,多个子字符串之间用空格隔开,当然,你也可以用变量。

foreach

原型:

$(foreach <var>,<list>,<text>)

功能:

这个函数的意思是,把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行< text>;所包含的表达式。每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。

例子:

names := a b c d
files := $(foreach n,$(names),$(n).o)

上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。

注意,foreach中的;参数是一个临时的局部变量,foreach函数执行完后,参数;的变量将不在作用,其作用域只在foreach函数当中。

例子一

  • makefile.md
#编译器管理
CC = gcc
RM = rm
MV = mv
AR = ar

PLATFORM = linux
ROOT_DIR = .
# 定义main 函数的名称
MAIN_FUNCTION ?= dsc_encode
BUILD_TIME               = 2020
BUILD_TIME              ?= $(shell date +%Y%m%d%H%M%S)
TARGET_NAME = $(TARGET_DIR)/$(MAIN_FUNCTION)
LIB_NAME   = $(TARGET_DIR)/lib$(MAIN_FUNCTION)



#打印日志是否添加颜色
# LOG_COLOR_EANBLE         = "Y"
#目录管理
TARGET_DIR=./target
OBJS=./objs

# 库文件路径
CCODE_DIRS = $(ROOT_DIR)/Huffman \
        $(ROOT_DIR)/list_struct \
        $(ROOT_DIR)/netfun \
        $(ROOT_DIR)/toolC  \
        $(ROOT_DIR)/compress \
        $(ROOT_DIR)/gcompress \
        $(ROOT_DIR)/gzip \
        $(ROOT_DIR)/mydiff \
        $(ROOT_DIR)/crc




CCODE_INC   += -I . -I include

# 非库文件
USER_DIRS =$(ROOT_DIR)/main
USER_INCS = .
# 入口函数文件
MAIN_FILE = $(ROOT_DIR)/main/$(MAIN_FUNCTION).c

HAL_DIRS =  $(ROOT_DIR)/HAL/common \
            $(ROOT_DIR)/HAL/$(PLATFORM)/socket \
            $(ROOT_DIR)/HAL/$(PLATFORM)/thread


ifeq ($(LOG_COLOR_EANBLE),"Y")
CFLAGS +=-DLOG_COLOR_EANBLE
endif

CFLAGS += -Wall -Wno-format-extra-args -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Werror=implicit-int  -Werror=enum-compare -Werror=return-type -Werror=parentheses\
            -Wno-implicit-function-declaration -Wformat=0 -Wno-comment -Werror \
            -Wno-unused-variable -Wno-pointer-sign -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-value
CFLAGS += -lrt -g -L/usr/lib64/  -lpthread -lm
CFLAGS += -fPIC
CFLAGS += -O0 -DBUILD_TIME=\"$(BUILD_TIME)\"
CFLAGS += -D$(MAIN_FUNCTION)_main=main
  • makefile
include makefile.mk


# 平台宏变量 -- 开始
HAL_INC_DIR   = $(patsubst %,-I %,$(HAL_DIRS))
HAL_INC_DIR  += $(HAL_INC)
HAL_SRC_FILES = $(foreach N, $(HAL_DIRS),$(wildcard $(N)/*.c))  #获取所有.c文件
HAL_COMPILE_FILES  = $(addprefix $(OBJS)/,$(HAL_SRC_FILES:.c=.o) ) #加上输出目录
# 库宏变量 -- 结束

# 库宏变量 -- 开始
CCODE_UNIT_INC_DIR   = $(patsubst %,-I %,$(CCODE_DIRS))
CCODE_UNIT_INC_DIR  += $(CCODE_INC)
CCODE_UNIT_SRC_FILES = $(foreach N, $(CCODE_DIRS),$(wildcard $(N)/*.c)) #获取所有.c文件
CCODE_COMPILE_FILES  = $(addprefix $(OBJS)/,$(CCODE_UNIT_SRC_FILES:.c=.o) ) #加上输出目录
# 库宏变量 -- 结束

# 用户变量 -- 开始
USER_INC_DIR   = $(patsubst %,-I %,$(USER_DIRS))
USER_INC_DIR   +=$(USER_INCS)
USER_SRC_FILES = $(foreach N, $(USER_DIRS),$(wildcard $(N)/*.c))    #获取所有.c文件
USER_COMPILE_FILES  = $(addprefix $(OBJS)/,$(USER_SRC_FILES:.c=.o) ) #加上输出目录
# 用户变量 -- 结束



target:CREATE_PATH
    @echo "ccode Files :" $(CCODE_DIRS)
    @echo "user Files  :" $(USER_DIRS)
    @echo "CCODE_UNIT_INC_DIR   :" $(CCODE_UNIT_INC_DIR)
    @echo "CCODE_UNIT_SRC_FILES :" $(CCODE_UNIT_SRC_FILES)
    @echo "CCODE_COMPILE_FILES  :"$(CCODE_COMPILE_FILES)
    @echo "HAL_INC_DIR          :" $(HAL_INC_DIR)
    @echo "HAL_SRC_FILES        :" $(HAL_SRC_FILES)
    @echo "HAL_COMPILE_FILES    :" $(HAL_COMPILE_FILES)
    @make $(TARGET_NAME).bin
    @make $(LIB_NAME).so

    @echo "========================================== success =========================================="
    @ls -lh $(TARGET_NAME).bin
    @ls -lh $(LIB_NAME)*
    @echo "============================================================================================="

CREATE_PATH:
    @echo "mkdir project dir " $(TARGET_DIR) $(OBJS)
    @mkdir -p $(TARGET_DIR)
    @mkdir -p $(OBJS)
    @mkdir -p $(patsubst %,$(OBJS)/%,$(CCODE_DIRS) $(USER_DIRS) $(HAL_DIRS) )


$(TARGET_NAME).bin:$(HAL_COMPILE_FILES) $(USER_COMPILE_FILES) $(LIB_NAME).a
    $(CC) -o $@ $^ $(CFLAGS)


$(LIB_NAME).a:$(CCODE_COMPILE_FILES)
    $(AR) rcf $@ $^

$(LIB_NAME).so:$(CCODE_COMPILE_FILES)
    $(CC) -shared -o $@ $^

#编译.o文件
$(OBJS)/%.o: %.c
    @echo "src:" $<
    @echo "src obj:" $@
    $(CC) -c $< -o $@  $(CFLAGS) $(CCODE_UNIT_INC_DIR) $(USER_INC_DIR) $(HAL_INC_DIR)

clean:
    $(RM) -rf $(OBJS) $(TARGET_DIR)

文章作者: Alex.Lin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex.Lin !
  目录