首页
chatGPT
关于
友链
其它
统计
更多
壁纸
留言
Search
1
cgroup--(4)cgroup v1和cgroup v2的详细介绍
6,456 阅读
2
修改Linux Kernel defconfig的标准方法
6,399 阅读
3
Android系统之VINTF(1)manifests&compatibility matrices
6,000 阅读
4
使用git生成patch和应用patch
3,479 阅读
5
c语言的__attribute__
3,176 阅读
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
工具
软件工具
Bug
COMPANY
登录
Search
标签搜索
shell
Linux
c
uboot
Vim
vintf
Linux驱动
Android
device_tree
git
DEBUG
arm64
链表
数据结构
IDR
内核
ELF
gcc
ARM
网址
adtxl
累计撰写
367
篇文章
累计收到
14
条评论
首页
栏目
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
工具
软件工具
Bug
COMPANY
页面
chatGPT
关于
友链
其它
统计
壁纸
留言
搜索到
41
篇与
的结果
2021-02-07
vim入门--(2)移动
暂无简介
2021年02月07日
769 阅读
0 评论
0 点赞
2021-02-04
Make--(4)命令
make命令实质上就是一个单行shell脚本。实际上,make会获取每行命令并将它传递给subshell去执行。事实上,make会进行优化,make会通过在每个命令行中扫描shell特殊字符来进行此项检查。如果不存在任何shell特殊字符,make就会直接执行此命令,而不会将此命令传递给subshell去执行。make默认使用/bin/sh这个shell。如果需要变更,可以通过在makefile中明确设定SHELL这个变量。
2021年02月04日
989 阅读
0 评论
0 点赞
2021-02-04
Make--(2)变量与宏
一个变量名称几乎可以由任何字符组成,包括大部分的标点符号。即使是空格也可以使用,但请不要这样做。事实上,只有:、\#和=等字符不允许使用在变量名称中。请注意,变量名称是区分大小写的。建议使用的命名习惯:当变量用来表示用户在命令行上或环境中所自定义的常数时,习惯上全部以大写来命名,单词之间用下划线隔开。至于只在makefile中出现的内部变量,则全部用小写来编写其名称,单词之间以下划线符号隔开。内含用户自定义函数的变量以及宏都会以小写来编写其名称,单词之间以破折号(-)隔开。1.自动变量自动变量含义$@ 工作目标的文件名$%档案文件成员(archive member)结构中的文件名元素。$<第一个必要条件的文件名$?时间戳在工作目标(的时间戳)之后的所有必要条件,并以空格隔开这些必要条件$^所有必要条件的文件名,并以空格隔开这些文件名。这份列表已删掉重复的文件名,因为对大多数的应用而言,比如编译、复制等,并不会用到重复的文件名$+ 如同$^,代表所有必要条件的文件名,并以空格隔开这些文件名。不过,$+包含重复的文件名。$*工作目标的主文件名。一个文件名称是由两部分组成:主文件名(stem)和扩展名(suffix)2. 变量的类型一般来说,以变量来代表外部程序是一个不错的注意,这让makefile的用户较容易针对他们特有的环境来改写makefile。变量可用来保存简单的常数,也可用来存放自定义的命令序列。例如下面的设定可用来汇报尚未使用的磁盘空间:DF = df AWK =awk free-space := $(DF) . | $(AWK) 'NR == 2 {print $$4}'make的变量有两种类型:经简单扩展的变量(simply expanded variable)以及经递归扩展的变量(recursively expanded variable)。经简单扩展的变量使用:=赋值运算符来定义一个经简单扩展的变量,如MAKE_DEPEND := $(CC) -M一旦make从makefile中读进该变量的定义语句,赋值运算符的右边部分会立刻被扩展。赋值运算符的右边部分只要出现make变量的引用就会被扩展,而扩展后所产生的的文本则会被存储成该变量的值。上面的变量被扩展之后就变成下面这样gcc -M然而,如果上面的CC变量尚未定义,则变量被扩展后将变成<space>-M未被定义的变量将被扩展为空值经递归扩展的变量直接使用=来定义,如MAKE_DEPEND = $(CC) -M ... # 稍后 CC = gccmake在读取变量时只会将=号右边的值赋值给变量,不会做任何的展开的动作,展开的动作会被延迟到该变量被使用的时候才进行。这样,当MAKE_DEPEND被使用的时候,即使CC并未定义,MAKE_DEPEND在脚本的值也会被扩展成gcc -M2.1 其他的赋值类型条件赋值?=此运算只会在变量的值尚不存在的状况下进行变量要求赋值的动作。附加运算符+=此运算符会将文本附加到变量里。当递归变量被使用时,赋值运算符右边部分的值会在"不影响变量中原有值的状况下"被附加到变量里。3. 宏变量适合用来存储单行形式的值,可是对于多行形式的值,例如命令脚本,如果我们想在不同的地方执行它,该怎么办?在GNU make中,我们可以通过define指令以创建“封装命令序列”(canned sequence)的方式来解决此问题,在这里简称为宏。例如,define build_target_with_subfeature_country @echo build_target_with_subfeature_country...... $(call build_target,$(filter $(TARGETS),$(subst _, ,$(1))),$(filter $(SUBFEATURE),$(subst _, ,$(1))),$(filter $(COUNTRY),$(subst _, ,$(1)))) endef define指令后面跟着变量名称以及一个换行符号。变量的主体包含了所有命令序列(每一行命令都必须前置一个Tab符号)直到ended关键字出现为止,endef关键字必须自成一行。在echo命令前置了一个@字符。当执行命令脚本时,前置@字符的命令不会被make输出。因此,当我们运行echo命令本身,只会输出该命令的输出。如果在宏内部使用@前缀,这个前缀字符只会影响使用到它的命令行。然而,如果将这个前缀字符用在宏引用上,则整个宏主体都会被隐藏起来。4. 何时扩展变量当make运行时。它会以两个阶段来完成它的工作。第一个阶段,make会读进makefile以及被引入的任何其他makefile。这个时候,其中所定义的变量和规则会被加载进make的内部数据库,而且依存图也会被建立起来。第二个阶段,make会分析依存图并且判断需要更新的工作目标,然后执行脚本以完成所需要的更新动作。当make在处理递归变量或define指令的时候,会将变量里的每一行或宏的主体存储起来,包括换行符号,但不会予以扩展。宏定义里的最后一个换行符号并不会被存储成宏的一部分;否则,宏被扩展时make会读进一个额外的换行符号。当宏被扩展时,make会立即扫描被扩展的文本中是否存在宏或变量的引用,如果存在就予以扩展,如此递归进行下去。如果宏是在命令脚本的语境中被扩展的,则宏主体的每一行都会被插入一个前导的跳格符(Tab)。下面是用来处理“makefile中的元素何时被扩展”的准则:对于变量赋值,make会在第一阶段读进该行时,立即扩展赋值运算符左边的部分。=和?=的右边部分会被延后到它们被使用的时候扩展,并且在第二阶段进行。:=的右边部分会被立即扩展如果+=的左边部分原本就被定义成一个简单变量,+=的右边部分就会被立即扩展,否则,它的求值动作会被延后。对于宏定义(使用define指令),宏的变量名称会被立即扩展,宏的主体会被延后到被使用的时候扩展对于规则,工作目标和必要条件总是会被立即扩展,然而命令总是会被延后扩展定义何时扩展a何时扩展ba = b立即延后a ?= b立即延后a := b立即立即a += b立即延后或立即define ab...endef立即延后一个通则是总是先定义变量和宏,然后再使用它们。尤其是,在工作目标或必要条件中使用变量时,就需要在使用变量之前予以定义。5. 工作目标与模式的专属变量在makefile运行期间,变量通常只有一个值。对需要经过两个处理阶段的makefile来说是这样没错。第一个阶段,make读进makefile之后,会对变量进行赋值和扩展的动作并建立依存图。第二个阶段,make会分析以及遍历依存图。所以,等到make指令命令脚本的时候,所有的变量都已经处理完毕了。但是如果我们想为特定的规则或模式重新定义变量,该怎么办?例如,现在我们想要编译一个需要额外命令行选项-DUSE_NEW_MALLOC=1的文件,但是其他的编译项目并不需要这个额外的命令行选项:gui.o: gui.h $(COMPILE.c) -DUSE_NEW_MALLOC=1 $(OUTPUT_OPTION) $<当规则有改动,或者有许多这样的文件需要处理,就会做很多重复的动作。为了解决此类问题,make提供了工作目标的专属变量。这些变量的定义会附加在工作目标之上,且只有该工作目标以及相应的任何必要条件被处理的时候,它们才会起作用。通过使用专属变量,可以把前面的例子改写为gui.o: CPPFLAGS += -DUSE_NEW_MALLOC=1 gui.o: gui.h $(COMPILE.c) $(OUTPUT_OPTION) $<工作目标的专属变量的语法如下所示:target...: variable = value target...: variable := value target...: variable += value target...: variable ?= value这类变量的赋值动作会延后到开始处理工作目标的时候进行。所以赋值运算符右边部分的值,可由另一个工作目标的专属变量来设定。同样地,此变量只有在必要条件的处理期间,才会发生作用。6. 变量来自何处文件在文件中创建,或者通过include指令引入命令行直接在make命令行上定义或重新定义变量:$ make CFLAGS=-g CPPFLAGS='-DBSD -DDEBUG'在命令行上,每个变量赋值运算符的右边部分必须是一个单独的shell参数。如果变量的值(或变量本身)包含空格,则必须为参数加上括号或是规避空格。命令行上变量的赋值结果将会覆盖掉环境变量以及makefile文件中的赋值结果。还可以使用:=或=赋值运算符将命令行参数设定成简单或递归变量。此外,如果使用override指令,你还可以要求make采用makefile的赋值结果,而不要采用命令行的赋值结果。环境make启动时,所有来自环境的变量都会被自动定义成make的变量。这些环境变量的优先级很低,所以makefile文件或命令行参数的赋值结果将会覆盖掉环境变量的值。不过,可以使用--environment-overrides或-e命令行选项,让环境变量覆盖掉相应的makefile变量。当make被递归调用时,有若干来自上层的make变量会通过环境传递给下层的make。默认情况下,只有原先就来自环境的变量会被导出到下层的环境之中。不过,你只要使用export指令就可以让任何变量被导出到环境之中:要求将所有变量全部导出,可以这么做:export请注意,即使这些变量的名称包含了无效的shell变量字符,make也会进行导出的动作。使用unexport可以避免环境变量被导出到子进程条件赋值运算符与环境变量的交互良好。假如你已经在makefile中定义了输出目录,但是你希望用户能轻易地改写,使用条件赋值运算符将会是最佳解决方案:# 假设输出目录为$(PROJECT_DIR)/out OUTPUT_DIR ?= $(PROJECT_DIR)/out使用下面的较冗长的方式同样可以实现同样的效果ifndef OUTPUT_DIR # 假设输出目录为$(PROJECT_DIR)/out OUTPUT_DIR = $(PROJECT_DIR)/out endif其中的差别在于,如果变量的值已经设定,那么即使是空值,条件赋值运算符也会跳过赋值的动作,而运算符ifdef和ifndef只会测试“非空值”。因此,我们会使用条件运算符而不会使用ifdef来对OUTPUT_DIR赋值。不建议过多的使用环境变量自动创建最后,make会在执行一个规则的命令脚本之前立刻创建自动变量。7. 条件指令条件指令的基本语法如下所示:if-condition text if the condition is true endif或:if-condition text if the condition is true else text if the condition is false endif其中,if-condition可以是以下之一:ifdef variable-name ifndef variable-name ifeq test ifneq test进行ifdef/ifndef的测试时,不应该以$()括住variable-name。最后,test可以表示成下面这样 "a" "b" 或 (a,b)其中,单引号或双引号可以交替使用(但是引号必须成对出现)。条件处理指令可用在宏定义和命令脚本中,还可以放在makefile的顶层:libGui.a: $(gui_objects) $(AR) $(ARFLAGS) $@ $< ifdef RANLIB $ (RANLIB) $@ endif我喜欢缩排我的条件指令,但是草率的缩排动作可能会导致错误。在前面的例子中,条件指令被缩排了四个空格,而且其所括住的命令具有一个前导的tab符号。如果其所括住的命令并非以一个tab符开头,make将不会把它视为命令;如果条件指令具有一个前导的tab符,make会误以为"条件指令"就是"命令"而将之传递给subshell。ifeq和ifneq条件指令可用来测试其参数是否相等。条件指令里空格的处理有些微妙。举例来说,如果参数采用小括号的形式,那么逗号之后的空格将会被忽略,除此之外所有其他的空格都是有意义的:ifeq (a, a) # These are equal endif ifeq ( b, b ) # So are these endif我比较喜欢使用等效的引号形式:ifeq "a" "a" # These are equal endif ifeq 'b' 'b' # So are these endif即使如此,还是经常会发生"变量扩展后包含了非预期的空格符号"的状况。这可能引发一些问题,因为进行匹配时会将所有字符纳入考虑。为了创建更稳定的makefile,我们会使用strip函数。ifeq "$(strip $(OPTIONS))" "d" COMPILATION_FLAGS += -DDEBUG endif8. include指令用法include xxx.mk引入文件与依存关系当make看到include指令时,会事先对通配符以及变量引用进行扩展的动作,然后试着读进include的文件。如果这个文件存在,则整个处理过程会继续下去;然而,如果这个文件不存在,则make会汇报问题并且继续读取其余的makefile。当所有的读取动作皆已完成之后,make会从规则数据库中找出任何可用来更新引入文件的规则。如果找到了一个相符的规则,make就会按照正常的步骤来更新工作目标。如果任何一个引入文件被规则更新,make接着会清楚它的内部数据库并且重新读进整个makefile。如果完成读取、更新和重新读取的过程之后,仍有include指令因为文件不存在而执行失败,那么make就会显示错误状态并终止执行。如果想让make忽略无法加载的引入文件,可以为include指令前置一个破折号-include xxx.mk 9. 标准的make变量除了自动变量,make还会为“自己的状态以及内置规则的定义”提供变量,以便对外提供相关信息:MAKE_VERSIONGNU make的版本号CURDIR正在执行make进程的当前工作目录。此变量的值将会是shell变量PWD的值,除非make在运行时用到了--directory(或-C)选项。--directory选项会使得make在搜索任何makefile之前变更到不同的目录。这个选项的完整形式为--directory=directory-name或-C directory-name。这样,CURDIR将会包含--include-dir的目录参数。在makefile文件中,所有路径都应该被设定成相对于makefile所在的目录。需要使用绝对路径时可以通过CURDIR进行访问。MAKEFILE_LISTmake所读进的各个makefile文件的名称所构成的列表,包括默认的makefile以及命令行或include指令所指定的makefile。在每个makefile被读进make之前,其文件名会被附加到MAKEFILE_LIST变量里。所以,任何一个总是可以查看此列表的最后一项来判断自己的文件名。MAKECMDGOALS对当前运行的make而言,make运行时命令行上指定了哪些工作目标。此变量并不包含命令行选项或变量的赋值。.VARIABLES到目前为止,make从各个makefile文件所读进的变量的名称所构成的列表,不含工作目标的专属变量。此变量仅供读取,对它所进行的任何赋值动作都会被忽略掉。
2021年02月04日
760 阅读
0 评论
0 点赞
2021-02-04
Make--(3)函数
1. 用户自定义函数用户自定义函数能够将命令序列存储在变量里,让我们得以在makefile中使用各种应用程序。2.内置函数make的内置函数可分类为:字符串操作、文件名操作、流程控制、用户自定义函数以及若干重要的杂项函数。所有的函数都会具有如下形式:$(function-name arg1[, argn])$(之后是内置函数的名称,接着是函数的参数。第一个参数的前导空格会被删除,但是后续的任何参数若包含前导(当然也包括内置的和结尾的)空格则都会被保留下来。函数的参数是以逗号为分隔符,所以只有一个参数的函数并不需要使用逗号。许多只接受一个函数的参数会把它的参数视为一串以空格隔开的单词。对这些函数而言,它们会以空格作为分隔符。2.1 字符串函数1. filter函数名称:过滤函数filter格式:$(filter <pattern...>,<text> )返回:返回符合模式<pattern>的字串。功能:以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。实例:sources := foo.c bar.c baz.s ugh.h foo: $(sources) cc $(filter %.c %.s,$(sources)) -o foo $(filter %.c %.s,$(sources))返回的值是“foo.c bar.c baz.s”。2. filter-out函数名称:反过滤函数filter-out格式:$(filter-out <pattern...>,<text> )返回:返回不符合模式<pattern>的字串。功能:以<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。实例:objects=main1.o foo.o main2.o bar.o mains=main1.o main2.o $(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o”。 3. findstring函数名称:查找字符串函数格式:$(findstring <find>,<in> )返回:如果找到,那么返回<find>,否则返回空字符串。功能:在字串<in>中查找<find>字串。实例:str1 := a b c str2 := b c 第一个函数返回“a”字符串,第二个返回空字符串 all: @echo $(findstring a,$(str1)) @echo $(findstring a,$(str2))4. subst函数名称:字符串替换函数格式:$(subst <search-string>, <replace-string>, <text>)返回:函数返回被替换过后的字符串。功能:把字串<text>中的<from>字符串替换成<to>,不具备通配符能力,它最常被用来在文件名列表中将一个扩展名替换成另一个扩展名。实例:$(subst a,the,There is a big tree) 把“There is a big tree”中的“a”替换成“the”,返回结果是“There is the big tree”。5. patsubst函数名称:模式字符串替换函数格式:$(patsubst <search-pattern>,<replace-pattern>,<text> )返回:函数返回被替换过后的字符串,具备通配符能力。此处的模式只可以包含一个%字符。功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<search-pattern>,如果匹配的话,则以<replace-pattern>替换。这里,<search-pattern>可以包括通配符“%”,表示任意长度的字串。如果<replace-pattern>中也包含“%”,那么,<replace-pattern>中的这个“%”将是<search-pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)实例:$(patsubst %.c,%.o,x.c.c bar.c) 把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”6. words函数名称:返回单词数量格式:$(words text)返回:text中的单词数量功能:返回text中单词数量。其中,$(word n,text)返回text中的第n个单词,第一个单词的编号是1.如果n的值大于text中单词的个数,则此函数将返回空值实例:current := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))通过这种方式可以获得列表中的最后一个单词,在这里将返回最近读取的makefile的文件名。7. firstword函数名称:格式:$(firstword text)返回:功能:此函数返回text中的第一个单词。此功能等效于$(word 1,text)实例:8. wordlist函数名称:格式:$(wordlist start,end,text)返回:返回text中范围从start(含)到end(含)的单词。如果start的值大于单词的个数,返回空值。如果end的值大于单词的个数,则函数返回从start开始的所有单词。功能:实例:2.2 重要的杂项函数1. sort函数名称:sort函数格式:$(sort list)返回:返回按照字典编纂顺序排列的不重复的单词列表,并以空格作为分隔符。功能:sort函数会排序它的list参数并移除重复的项目。此外,sort函数还会删除前导以及结尾的空格。实例:2. shell函数名称:shell函数格式:$(shell <fun>)返回:shell函数的返回值。输出中所出现的一系列换行符号会被缩减成单一空格符号,任何接在后面的换行符号都会被删除。标准错误以及任何程序的结束状态都不会被返回。功能:为了使用shell的函数实例:例如files := $(shell echo *.c)2.3 文件名函数makefile的编写者通常会花许多时间在文件的处理上。1. wildcard函数名称:通配符展开函数格式:$(wildcard PATTERN...)返回:如果被扩展的模式找不到相符的文件,则会返回空字符串。功能:在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”实例:一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。2. dir函数名称:格式:$(dir list...)返回:功能:dir函数返回list中每个单词的目录部分。实例:3. notdir函数名称:格式:$(notdir name...)返回:功能:notdir函数返回文件路径的文件名部分。实例:4. suffix函数名称:格式:$(suffix name...)返回:功能:suffix函数会返回它的参数中每个单词的后缀(即文件扩展名)实例:5. basename函数名称:格式:$(basename name...)返回:功能:实例:6. addsuffix函数名称:格式:返回:功能:实例:7. addprefix函数名称:格式:返回:功能:实例:8. join函数名称:格式:返回:功能:实例:2.4 流程控制4. foreach函数名称:循环替换函数格式:$(foreach <var>,<list>,<text> )返回:返回循环<text>语句最终执行的结果功能:把参数<list>中的单词逐一取出放到参数<var>所指定的变量中, 然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环这个过程。实例:letters := $(foreach letter, a b c d, $(letter)) show-words: # letters has $(words $(letters)) words: `$(letters)` $ make # letters has 4 words: 'a b c d'当这个foreach函数被执行时,它会反复扩展循环主体$(letter),并且将循环控制变量letter的值依次设定成a、b、c、d。每次扩展所得到的文本会被累积起来,并以空格为分隔符。2.5 较不重要的杂项函数7. strip函数名称:去空字符函数格式:$(strip <string> )返回:返回被去掉空格的字符串值。功能:去掉<string>字串中开头和结尾的空字符,并将中间的多个连续空字符(如果有的话)合并为一个空字符实例:str1 := abc str2 := abc str3 := a b c all: @echo $(strip $(str1)) @echo $(strip $(str2)) @echo $(strip $(str3)) 输出结果: abc abc a b c 10. call函数名称:call函数是唯一一个可以创建定制化参数函数的引用函数。支持对自定义函数的引用;格式:$(call VARIABLE,PARAM,PARAM,...)返回:VARIABLE展开后的表达式的值功能:在执行时,将它的参数"PARAM"依次赋给临时变量"(1)","(2)".call对参数的数目没有限制,也可以没有参数值。最后再对VARIABLE展开后的表达式进行处理.说明:变量VARIABLE在定义时最好定义为递归展开式;call函数中对VARIABLE的调用,直接给函数或变量名就好了,不要用"$";多个PARAM使用逗号分割开,且逗号和PARAM之间不能有空格,否则会导致解析异常;实例:(1)变量的引用变量定义为直接展开式如果这里将VARIABLE1定义为直接展开式,最终调用call函数后,返回值为空我的理解是,直接展开式在定义时将(1)和(2)展开,而此时它们的值为空,所以变量的值为空.当执行到call函数时,尽管带上了需要传递的参数,但PARAM((1)和(2))之前已经被展开了,故此时已经取不到传递进来的参数值.VARIABLE1 := $(2) $(1) $(info 1-$(VARIABLE1)) aa=$(call VARIABLE1,hello,world) $(info 1-$(aa)) all: @echo Done定义为递归展开式VARIABLE1 = $(2) $(1) $(info 2-$(VARIABLE1)) aa=$(call VARIABLE1,hello,world) $(info 2-$(aa)) all: @echo Done(2)函数的引用不带参数的函数引用define FUNC1 $(info echo 3-"hello") endef $(call FUNC1) all: @echo Done 带参数的函数引用define FUNC1 $(info echo 4-$(1) $(2)) endef $(call FUNC1,hello,wolrd) all: @echo Done 1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:1. patsubst函数名称:格式:返回:功能:实例:
2021年02月04日
828 阅读
0 评论
0 点赞
2021-02-04
Make--(1)规则
makefile中的工作目标依存于一组必要条件,这些条件一般也都是文件。当你要求更新某个工作目标时,如果必要条件中存在时间戳在工作目标的时间戳之后的文件,make就会执行相应规则里的命令脚本。因为某个规则的工作目标可以是另一个规则的必要条件,所以这样的工作目标和必要条件将会形成依存图(dependency graph)。建立及处理依存图,并据此更新特定的工作目标,就是make所要做的事。规则对make而言十分重要,make允许你使用各种类型的规则。
2021年02月04日
821 阅读
0 评论
0 点赞
2021-02-03
shell简介--(13)文件包含
注:本文转载自菜鸟教程和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。Shell 文件包含的语法格式如下:. filename # 注意点号(.)和文件名中间有一空格 或 source filename
2021年02月03日
794 阅读
0 评论
0 点赞
2021-02-03
shell简介--(12)输入/输出重定向
注:本文转载自菜鸟教程大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。重定向命令列表如下:命令说明command > file将输出重定向到filecommand < file将输入重定向到filecommand >> file将输出以追加的方式重定向到filen > file将文件描述符为n的文件重定向到filen >> file将文件描述符为 n 的文件以追加的方式重定向到 filen >& m将输出文件 m 和 n 合并n <& m将输入文件 m 和 n 合并<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入。注:需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。输出重定向重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:command1 > file1上面这个命令执行command1然后将输出的内容存入file1。注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。输入重定向和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:command1 < file1这样,本来需要从键盘获取输入的命令会转移到文件读取内容。注意:输出重定向是大于号(>),输入重定向是小于号(<)。command1 < infile > outfile同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。重定向深入理解一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。如果希望 stderr 重定向到 file,可以这样写:command 2>file如果希望 stderr 追加到 file 文件末尾,可以这样写:command 2>>file2 表示标准错误文件(stderr)。如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:$ command > file 2>&1 或者 $ command >> file 2>&1如果希望对 stdin 和 stdout 都重定向,可以这样写:$ command < file1 >file2command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。Here DocumentHere Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。它的基本的形式如下:command << delimiter document delimiter它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。注意: 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。 开始的delimiter前后的空格会被忽略掉。实例在命令行中通过 wc -l 命令计算 Here Document 的行数:$ wc -l << EOF 欢迎来到 菜鸟教程 www.runoob.com EOF 3 # 输出结果为 3 行 $我们也可以将 Here Document 用在脚本中,例如:#!/bin/bash # author:菜鸟教程 # url:www.runoob.com cat << EOF 欢迎来到 菜鸟教程 www.runoob.com EOF执行以上脚本,输出结果:欢迎来到 菜鸟教程 www.runoob.com/dev/null文件如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:$ command > /dev/null/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。如果希望屏蔽 stdout 和 stderr,可以这样写:$ command > /dev/null 2>&1注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。
2021年02月03日
799 阅读
0 评论
0 点赞
2021-02-03
shell简介--(11)函数
注:本文转载自菜鸟教程shell 函数linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。shell中函数的定义格式如下:[ function ] funname [()] { action; [return int;] }说明:1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。2、参数返回,可以显式加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255#!/bin/bash # author:菜鸟教程 # url:www.runoob.com demoFun(){ echo "这是我的第一个 shell 函数!" } echo "-----函数开始执行-----" demoFun echo "-----函数执行完毕-----"输出结果:-----函数开始执行----- 这是我的第一个 shell 函数! -----函数执行完毕-----下面定义一个带有return语句的函数:#!/bin/bash # author:菜鸟教程 # url:www.runoob.com funWithReturn(){ echo "这个函数会对输入的两个数字进行相加运算..." echo "输入第一个数字: " read aNum echo "输入第二个数字: " read anotherNum echo "两个数字分别为 $aNum 和 $anotherNum !" return $(($aNum+$anotherNum)) } funWithReturn echo "输入的两个数字之和为 $? !"输出类似下面:这个函数会对输入的两个数字进行相加运算... 输入第一个数字: 1 输入第二个数字: 2 两个数字分别为 1 和 2 ! 输入的两个数字之和为 3 !函数返回值在调用该函数后通过 $? 来获得。注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。函数参数在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...带参数的函数示例:#!/bin/bash # author:菜鸟教程 # url:www.runoob.com funWithParam(){ echo "第一个参数为 $1 !" echo "第二个参数为 $2 !" echo "第十个参数为 $10 !" echo "第十个参数为 ${10} !" echo "第十一个参数为 ${11} !" echo "参数总数有 $# 个!" echo "作为一个字符串输出所有参数 $* !" } funWithParam 1 2 3 4 5 6 7 8 9 34 73输出结果:第一个参数为 1 ! 第二个参数为 2 ! 第十个参数为 10 ! 第十个参数为 34 ! 第十一个参数为 73 ! 参数总数有 11 个! 作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。另外,还有几个特殊字符用来处理参数:参数处理说明$#传递到脚本或函数的参数个数$*以一个单字符串显示所有向脚本传递的参数$$脚本运行的当前进程的ID号$!后台运行的最后一个进程的ID号$@与$*相同,但是使用时加引号,并在引号中返回每个参数$-显示Shell使用的当前选项,与set命令功能相同$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误
2021年02月03日
739 阅读
0 评论
0 点赞
2021-02-01
shell简介--(10)流程控制
注:本文转载自菜鸟教程和Java、PHP等语言不一样,sh的流程控制不可为空if elseif 语句语法格式:if condition then command1 command2 ... commandN fi写成一行(适用于终端命令提示符):if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi末尾的fi就是if倒过来拼写,后面还会遇到类似的。if else 语法格式:if condition then command1 command2 ... commandN else command fiif else-if elseif else-if else 语法格式:if condition1 then command1 elif condition2 then command2 else commandN fi以下实例判断两个变量是否相等:a=10 b=20 if [ $a == $b ] then echo "a 等于 b" elif [ $a -gt $b ] then echo "a 大于 b" elif [ $a -lt $b ] then echo "a 小于 b" else echo "没有符合的条件" fi输出结果:a 小于 bif else 语句经常与 test 命令结合使用,如下所示:num1=$[2*3] num2=$[1+5] if test $[num1] -eq $[num2] then echo '两个数字相等!' else echo '两个数字不相等!' fi输出结果:两个数字相等!for循环与其他编程语言类似,Shell支持for循环。for循环一般格式为:for var in item1 item2 ... itemN do command1 command2 ... commandN done写成一行:for var in item1 item2 ... itemN; do command1; command2… done;当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的shell命令和语句。in列表可以包含替换、字符串和文件名。in列表是可选的,如果不用它,for循环使用命令行的位置参数。例如,顺序输出当前列表中的数字:for loop in 1 2 3 4 5 do echo "The value is: $loop" done输出结果:The value is: 1The value is: 2The value is: 3The value is: 4The value is: 5顺序输出字符串中的字符:#!/bin/bash for str in This is a string do echo $str done输出结果:This is a string注:通常情况下 shell 变量调用需要加 $,但是 for 的 (()) 中不需要,下面来看一个例子:#!/bin/bash for((i=1;i<=5;i++));do echo "这是第 $i 次调用"; done;执行结果:这是第1次调用 这是第2次调用 这是第3次调用 这是第4次调用 这是第5次调用与 C 中相似,赋值和下一步执行可以放到代码之前循环语句之中执行,这里要注意一点:如果要在循环体中进行 for 中的 next 操作,记得变量要加 $,不然程序会变成死循环。while语句while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:while condition do command done以下是一个基本的while循环,测试条件是:如果int小于等于5,那么条件返回真。int从0开始,每次循环处理时,int加1。运行上述脚本,返回数字1到5,然后终止。#!/bin/bash int=1 while(( $int<=5 )) do echo $int let "int++" done运行脚本,输出:1 2 3 4 5以上实例使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量while循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量FILM,按<Ctrl-D>结束循环。echo '按下 <CTRL-D> 退出' echo -n '输入你最喜欢的网站名: ' while read FILM do echo "是的!$FILM 是一个好网站" done运行脚本,输出类似下面:按下 <CTRL-D> 退出 输入你最喜欢的网站名:菜鸟教程 是的!菜鸟教程 是一个好网站无限循环无限循环语法格式:while : do command done或者while true do command done或者for (( ; ; ))until循环until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。until 语法格式:until condition do command donecondition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。以下实例我们使用 until 命令来输出 0 ~ 9 的数字:#!/bin/bash a=0 until [ ! $a -lt 10 ] do echo $a a=`expr $a + 1` done运行结果:0 1 2 3 4 5 6 7 8 9case esaccase ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case ... esac 语法格式如下:case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esaccase 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。下面的脚本提示输入 1 到 4,与每一种模式进行匹配:echo '输入 1 到 4 之间的数字:' echo '你输入的数字为:' read aNum case $aNum in 1) echo '你选择了 1' ;; 2) echo '你选择了 2' ;; 3) echo '你选择了 3' ;; 4) echo '你选择了 4' ;; *) echo '你没有输入 1 到 4 之间的数字' ;; esac输入不同的内容,会有不同的结果,例如:输入 1 到 4 之间的数字: 你输入的数字为: 3 你选择了 3下面的脚本匹配字符串:#!/bin/sh site="runoob" case "$site" in "runoob") echo "菜鸟教程" ;; "google") echo "Google 搜索" ;; "taobao") echo "淘宝网" ;; esac输出结果为:菜鸟教程跳出循环在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。break命令break命令允许跳出所有循环(终止执行后面的所有循环)。continuecontinue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
2021年02月01日
769 阅读
0 评论
0 点赞
2021-02-01
shell简介--(9)test命令
注:本文转载自菜鸟教程数值测试参数说明-eq等于则为真-ne不等于则为真-gt大于则为真-ge大于等于则为真-lt小于则为真-le小于等于则为真num1=100 num2=100 if test $[num1] -eq $[num2] then echo '两个数相等!' else echo '两个数不相等!' fi输出结果:两个数相等!代码中的 [] 执行基本的算数运算,如:#!/bin/bash a=5 b=6 result=$[a+b] # 注意等号两边不能有空格 echo "result 为: $result"结果为:result 为: 11字符串测试参数说明=等于则为真!=不相等则为真-z 字符串字符串的长度为零则为真-n 字符串字符串的长度不为零则为真num1="ru1noob" num2="runoob" if test $num1 = $num2 then echo '两个字符串相等!' else echo '两个字符串不相等!' fi输出结果:两个字符串不相等!文件测试参数说明-e 文件名如果存在则为真-r 文件名如果文件存在且可读则为真-w 文件名如果文件存在且可写则为真-x 文件名如果文件存在且可执行则为真-s 文件名如果文件存在且至少有一个字符则为真-d 文件名如果文件存在且为目录则为真-f 文件名如果文件存在且为普通文件则为真-c 文件名如果文件存在且为字符型特殊文件则为真-b 文件名如果文件存在且为块特殊文件则为真Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。例如:
2021年02月01日
721 阅读
0 评论
0 点赞
1
2
3
4
5