版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第三章 Shell编程,本章概要 什么是Shell脚本 正则表达式与grep命令 用Bash Shell编程,什么是Shell脚本? 一个shell脚本程序(shell script)是包含Linux命令的文本文件。 我们可以使用任何标准编辑器输入Linux命令。例如vi、emacs、WordPerfect,以及任何GNOME或KDE的文本编辑器。,3.1 Shell编程概述,一个Shell脚本就是一组Shell的命令和语句,把它们放在一个文件里。 可以交互式地运行这些脚本,也可以计划在未来的某个时间里自动地或无人监管地运行某个脚本。,举一个例子。 DOS在文本文件每一行的结尾都有一个换行符和
2、一个回车作为标记; Linux(其他UNIX系统也是一样)在每一行的最后只使用一个换行符。 如果我们使用带有-b选项的vi编辑器打开一个DOS文件,将看到在每一行在最后都有一个M符号。这个M代表ctrl+M,它表示的是回车符。 在Linux系统上,通过使用带-d选项的tr命令可以很容易地将DOS文本文件中的那些额外的回车符去掉。,为什么要建立Shell程序呢,tr命令字符翻译,tr用来从标准输入中通过替换或删除操作进行字符转换。tr主要用于删除文件中控制字符或进行字符转换。 使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。 tr刚执行时,字符串1中的字符被映射到字符串2
3、中的字符,然后转换操作开始。 大小写转换。 去除控制字符。 删除空行。,tr命令格式,troptionstring1string2 字符串string1中的输入字符映射到string2中的对应字符。 各选项的含义如下: -c 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII。 -d 删除字符串1中所有输入字符。 -s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。 注意:指定字符串1或字符串2的内容时,只能使用单字符或字符串范围或列表。,举例说明tr的用法: tr “a-z” “A-Z” /etc/passwd 把/etc/passwd文件输出到屏幕上
4、,并把所有的小写字母变成大写字母。 tr “a-z” “b-za” /.bashrc 把.bashrc输出到屏幕上,但是字符是经过循环处理的。,我们将一个名filename.dos的DOS文本文件转换为名为filename.linux的Linux文本文件。可以输入下面的命令: $tr d “015”filename.linux 注:015是用八进制数表示的回车符的ASCII码。 同许多UNIX程序一样,tr的读写操作都是针对标准输入和标准输出的设备,所以我们在此必须使用I/O的重定向,才能利用tr删除一个文件中所有指定字符,并将输出存入另一个文件中。,我们可以把下面这行存储到一个名为dos2l
5、inux的文件中: tr d “015” $2 (注:Bash有一些专门存储命令行参数的变量。在一个Shell脚本中,$0表示该Shell脚本的名字;变量$1 、$2等表示命令行参数。 ) 类比:在C程序中main函数参数表中的参数 main(int argc , char *argv) 然后,通过使用下面的命令将其做成可执行文件: $chmod +x dos2linux,假如我们有一个挂装为/dosc的MS-DOS分区,可以试用一下dos2linux这个Shell程序: $dos2linux /dosc/autoexec.bat aexec.bat,编写脚本和编写程序有什么不同,脚本和程序之
6、间的区别是,脚本是一个文本文件。在该文件里写命令并执行文件无需中间步骤。 反之,程序要运行必须对程序的源代码进行编译。由编译器生成计算机能够读懂的可执行机器代码。,Shell支持大多数编程语言结构,比如: 变量和数组 参数传递 逻辑和流程结构(ifthenelse块、与、或、非) case 语句 循环结构(until、while、for) 函数(内部及用户定义的) 注释脚本的文档,系统编程语言“从头开始”设计数据结构和算法,从最基本的内存单元开始设计;脚本语言则是在现有的多功能库基础上实现新功能。 系统编程语言是强类型语言,有助于处理复杂的问题;而脚本语言则一般不使用类型,用于简化元件之间的关
7、系,可以快速开发。,系统编程语言和脚本语言,系统编程语言的历史,系统编程语言先是作为汇编语言的替代品。汇编语言反映机器的每一个层面,每一条语句代表单一的机器指令。程序设计者要做很低级的事情,诸如调用寄存器、处理杂事等。因此,用汇编语言编写及维护大型程序,是相当困难的。 50年代晚期,高级语言如Lisp、FORTRAN和Algol出现了。程序员不再需要直接编写机器指令了,由编译器来负责把高级语言程序的源代码编译成可执行码。随着时间的推移,一系列的程序设计语言从Algol衍生出来,包括PL/1、Pascal、C、C+以及Java。,平均每行高级语言大约能编译成5行汇编语言。 系统编程语言的显著特点
8、是具有“类型”。类型是指信息的意义被事先指定的程度。 如C语言中定义int a;表示a这个变量被当作int使用,这就构成了C类型的一部分。 现代计算机系统基本上没有类型,内存单元可以存放任何值:整数、浮点数、指针或者指令等等。一个值的意义决定于它如何被使用。如果程序指针指向内存的某个单元,那该单元就被当作指令;如果一个单元被一个加法指令调用,那它就被当作整数。,强类型语言,目前所有系统编程语言都是强类型的。 每个变量都有类型,用法也须遵循该类型; 数据段与代码段完全分开,在线产生新代码相当困难; 变量可以放到结构或对象里面,该用A类型对象时就不能用B类型对象。,类型的优点,首先,类型把东西的用
9、途都说明清楚,又限定不同的东西要以不同的方式对待,因此大型程序就比较容易管理。 第二,编译器能由类型的信息产生最优化编码;如果编译器事先知道一个东西被作为整数来用,那么当它被拿来做加法时,编译器可以产生整数加法的指令。如果不知道的话,就要在执行时期检测,这样做的代价比较高昂。 第三,编译器能由类型的信息来找出特定种类的错误。例如,把一个浮点数当作指针来用。,脚本语言,脚本语言可以用来扩展已经存在元件的功能,而很少用来开发复杂的数据结构和算法,这些应该由元件提供。因此,脚本语言被称为连接语言(Glue Language)或者系统集成语言(System Intergration Language)
10、。 为了简化联结元件的工作,脚本语言通常没有类型。 脚本语言通常是字符串导向。因为这能对许多类型的变量提供单一的表示方法。 脚本语言比系统语言更高级。,脚本语言一般有一组元件已经用别的语言(一般为C语言)写成。 脚本语言不会从头开始,而是组合已经写好的元件。 如Tcl和VB可以用来管理GUI元件,而UNIX Shell可以把元件当作过滤器来组成一条“流水生产线”,最终产生所要的结果。,无类型的语言更容易结合元件,因为它并不对东西该如何使用做任何限制,而强类型语言不利程序代码的再利用。为了适应不同类型的数据,就得设计许多不同的表达方法。 脚本语言的效率一般比系统编程语言差。 脚本语言比系统语言更
11、高级,一行脚本语言相当于数百或数千行汇编语言,而一行系统编程语言只相当于5行。,综上所述,脚本语言用来开发应用程序的优点是开发速度快和易用性; 而系统编程语言的优点在于其能够实现复杂的功能、算法以及运行时的速度。,Shell提供了一套完整的字符串模式匹配规则,或者称之为元字符,这样就可以按照所要求的模式来匹配文件。 匹配文件名中的任何字符串。 匹配文件名中的单个字符。 匹配文件名中的字母或数字字符。 这些字符有* 、 ?、 . 等,当shell遇到上述字符时,就会把它们当作特殊字符,而不是文件名中的普通字符,这样用户就可以用它们来匹配相应的文件名。,3.2 shell中的元字符,shell中的
12、特殊字符,通配符 通配符用于模式匹配,如文件名匹配、路经名搜索、字符串查找等。常用的通配符有*、?和括在方括号 中的字符序列。 * 代表任何字符串(长度可以不等),例如:“f*”匹配以f打头的任意字符串。但应注意,文件名前的圆点(.)和路经名中的斜线(/)必须显式匹配。例如“*”不能匹配.file,而“.*”才可以匹配.file。,shell中的特殊字符,? 代表任何单个字符。 代表指定的一个字符范围,只要文件名中 位置处的字符在 中指定的范围之内,那么这个文件名就与这个模式串匹配。 方括号中的字符范围可以由直接给出的字符组成,也可以由表示限定范围的起始字符、终止字符及中间的连字符(-)组成。
13、,表通配符含义举例,特别需要注意的是: 连字符“-”仅在方括号内有效,表示字符范围,如在方括号外面就成为普通字符。 *和?只在方括号外面是通配符,若出现在方括号之内,它们也失去通配符的能力,成为普通字符了。 例如,模式“- a*?abc”中只有一对方括号是通配符,*和?均为普通字符,因此,它匹配的字符串只能是- a*abc和- a?abc。,例子: 为了列出所有以大写字母开头的文件名,可以用: $ ls A-Z* 为了列出所有以小写字母开头的文件名,可以用: $ ls a-z* 为了列出所有以数字开头的文件名,可以用: $ ls 0-9* 为了列出所有以. 开头的文件名(隐含文件,例如.pro
14、file、.rhosts、.history等等),可以用: $ ls .*,由于*、?和 对于shell来说具有比较特殊的意义, 在正常的文件名中不应出现这些字符; 特别是在目录名中不要出现它们。 否则Shell匹配起来可能会无穷的递归下去。,使用通配符时需要注意的问题,引用,脚本中执行行操作时, shell将对脚本设置予以解释。例如:,表 shell引用类型,“ ” 双引号 反引号 单引号 反斜线,需要引用的特殊元字符,; 命令分隔符 & 后台处理 ( ) 命令编组:创建子shell 命令编组:不创建子shell | 管道 输出重定向 newline 命令终止 space/tab 词分隔符
15、$ 变量替换字符 * ? 用于文件名展开的shell元字符,shell中的引号,在shell中引号分为三种:单引号,双引号和反引号。 单引号 由单引号括起来的字符都作为普通字符出现。特殊字符用单引号括起来以后,也会失去原有意义,而只作为普通字符解释。例如: $ string=$PATH $ echo $string $PATH $ 可见$保持了其本身的含义,作为普通字符出现。,双引号 “,由双引号括起来的字符,除$、和“这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待。 对于$来说,就是用其后指定的变量的值来代替这个变量和$; 对于而言,是转义字符,它告诉shell不要对其
16、后面的那个字符进行特殊处理,只当作普通字符即可。 这样,在双引号中需要在前面加上的只有四个字符$,和”本身。而对”号,若其前面没有加,则Shell会将它同前一个”号匹配。,例如,我们假定PATH的值为.:/usr/bin:/bin,输入如下命令: $ TestString”$PATH”$PATH” $ echo $TestString .:/usr/bin:/ bin”$PATH $,反引号 ,反引号()这个字符所对应的键一般位于键盘的左上角,不要将其同单引号()混淆。 反引号括起来的字符串被shell解释为命令行。 在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包
17、括两个反引号)部分。,反引号 ,例如: $ pwd /home/xyz $ string=”current directory is pwd” $ echo $string current directour is /home/xyz $,利用反引号的这种功能可以进行命令置换,即把反引号括起来的执行结果赋值给指定变量。例如: $ today=date $ echo Today is $today Today is Mon Apr 15 16:20:13 CST 2009 $ 反引号还可以嵌套使用。但需注意,嵌套使用时内层的反引号必须用反斜线()将其转义。例如: $ abc=echo The n
18、umber of users is who| wc-l $ echo $abc The number of users is 5 $,命令替换,命令替换和重定向有些相似,但区别在于命令替换是将一个命令的输出作为另外一个命令的参数。常用命令格式为: command1 command2 其中,command2的输出将作为command1的参数。需要注意的是这里的符号,被它括起来的内容将作为命令执行,执行后的结果作为command1的参数。 例如: $ cd pwd 该命令将pwd命令列出的目录作为cd命令的参数,结果仍然是停留在当前目录下。,反斜线,如果下一个字符有特殊含义,反斜线防止shell误
19、解其含义,即屏蔽其特殊含义。下述字符包含有特殊意义: & * + $ “ | ?。 假定echo命令加*,意即以串行顺序打印当前整个目录列表,而不是一个星号*。,为屏蔽星号特定含义,可使用反斜线。 上述语句同样可用于$ $命令, s h e l l解释其为现在进程I D号,使用反斜线屏蔽此意,仅打印$ $。,注释符,在shell编程中经常要对某些正文行进行注释,以增加程序的可读性。在Shell中以字符“#”开头的正文行表示注释行。,3.3 正则表达式与grep命令,3.3.1 正则表达式,3.3.2 grep的使用,UNIX的文本处理工具,UNIX工具很丰富,如ls、pwd、who、vi和so
20、rt等等。其中有三个是UNIX上最重要的文本处理工具:grep、sed和awk。 这些工具用于处理来自管道或标准输出的文本。实际上,sed和awk本身常被用做脚本语言。 而要使用grep、sed和awk的强大功能,就必须先学会使用正则表达式和正则表达式元字符。,当从一个文件或命令输出中抽取或过滤文本时,可以使用正则表达式。 什么是正则表达式(RE)? 正则表达式是一种字符模式,用于在查找过程中匹配相同的字符。 它由一些特殊元字符和普通的字符组成。,3.3.1 正则表达式,在大多数程序里,正则表达式都被括在两个正斜杠(/)之间。 例如: /love/ 就是一个正则表达式,在被查找的行中,模式lo
21、ve随时会被相同的模式匹配。 为了抽取或获取信息,我们必须描述抽取操作应遵循的一些规则。 这些规则由一些特殊字符或进行模式匹配操作时使用的元字符组成,也可以使用普通字符作为模式中的一部分进行搜索。 例如A将查询A,x将查询字母x。,Linux系统自带的所有大的文本过滤工具在某种模式下都支持正则表达式的使用。 下面我们所介绍的基本元字符使用在: grep(全局正则表达式版本,用于查找文件的内容) sed(流编辑,一种重要的文本过滤工具)命令中, AWK语言,结合(以字符出现的情况进行匹配的元字符)使用在AWK语言中。,表 基本元字符集及其含义,1使用句点匹配单字符,句点“.”可以匹配任意单字符。
22、 例如,如果要匹配一个字符串,以beg开头,中间夹一个任意字符,那么可以表示为 beg.n 。 在ls-l命令中,可以匹配一定权限: .x.x.x 此格式匹配用户本身、用户组及其他用户的执行权限。 drwxrwxrw- no match -rw-rw-rw- no match -rwxrwxr-x match -rwxr-xr-x match,假定正在过滤一个文本文件,对于一个有10个字符的脚本集,要求前4个字符之后为xc,后4个字符为任意。匹配操作如下: .xc. 按下例运行: 1234xc9088 match 4523xx9001 no match 0011xA9912 no match
23、9931xc3455 match 注意:句点“.”允许匹配ASCII集中任意字符,或为字母,或为数字。,2在行首以匹配字符串或字符序列,只允许在一行的开始匹配字符或单词。 例如使用ls-l命令,并匹配目录。 d drwxrwxrw- match -rw-rw-rw- no match drwxrwxr-x match -rwxr-xr-x no match,回到上个脚本,使用001,结果将匹配每行开始为001的字符串或单词: 1234xc9088 no match 4523xx9001 no match 0011xA9912 match 9931xc3455 no match,可以将各种模式结
24、合使用,例如: 4xc. 结果为: 1234xc9088 match 4523xx9001 no match 0011xA9912 no match 9931xc3455 no match 3224xc193 no match 在正则表达式中使用频繁,因为大量的抽取操作通常在行首。,3在行尾以$匹配字符串或字符,$与正相反,它在行尾匹配字符串或字符。$符号放在匹配单词之后。 例如: 要匹配每行以ld结尾的所有字符串。操作为ld$ 如果要匹配所有的空行,执行以下操作 $ 如果只返回包含一个字符的行,操作如下:.$ 如果在行尾匹配单词jet01,操作为jet01$,4使用*匹配字符串中的单字符或其
25、重复序列,使用*匹配任意字符或字符串的重复多次表达式。例如: compu*t 将匹配字符u一次或多次: computer computing compuuuuuute 10133* 匹配: 101333 10133 10133334444,5使用屏蔽一个特殊字符的含义,什么是特殊字符? 一般意义上,下列字符可以认为是特殊字符: $ . “ * ! ( ) + ? 假定要匹配包含字符“.”的各行,而“.”代表匹配任意单字符的特殊字符,因此需要屏蔽其含义。操作如下: . (上述模式不认为反斜杠后面的字符是特殊字符,而是一个普通字符,即句点.),6使用 匹配一个范围或集合,使用 匹配特定字符串或字符
26、串集,可以用逗号将括号内要匹配的不同字符串分开. 使用“-”表示一个字符的范围。 假定要匹配任意一个数字,可以使用0123456789,更可以简化为0-9。 假定要匹配任意字母,则使用A-Za-z 假定要匹配一个单词,以s开头,中间有一任意字母,以t结尾,则使用: sa-z A-Zt,要匹配computer或Computer两个单词,可做如下操作: Cc omputer 要匹配所有包含system后跟句点的所有单词,这里s可以大写或小写。使用如下操作: S,system. 结合*与更有效益。例如a-z A-Z*将匹配所有的单词。 注意符号的使用,当直接用在一个括号里,意指否定或不匹配括号里的内
27、容。 a-z A-Z 匹配任一非字母型字符 0-9 匹配任一非数字型字符,7使用匹配模式结果出现的次数,模式有三种形式,即: patternn 匹配模式出现n次 patternn, 匹配模式出现最少n次 patternn,m 匹配模式出现n到m次之间, n、m为0255中任意整数。 请看例子。 匹配字母A出现2次,并以B结尾。操作如下: A2B (AAB) 匹配字母A出现至少4次,使用: A4,B (AAAAB,AAAAAAAB,但不能为AAAB),假定从下面列表中抽取代码. 格式如下:前4个字符是数字,接下来是xx,最后4个也是数字。 0-94xx0-94 结果: 1234xc9088 no
28、 match 4523xx9001 match 0011xA9912 no match 9931xc3455 no match,总结,在写正则表达式时,有点难度或达不到预期效果,可以: (1)在写正则表达式前先写下预期的输出结果。 (2)可以记住一些基本模式。,grep有三种变形: grep命令:一次只能搜索一个指定的模式; egrep命令:检索扩展的正则表达式(包括表达式组和可选项); fgrep命令:检索固定字符串,它不识别正则表达式,是快速搜索命令。,4.3.2 grep的使用,语法,这组命令在指定的输入文件中查找与模式匹配的行。如果没有指定文件,则从标准输入中读取。正常情况下,每个匹配
29、的行被显示到标准输出。如果要查找的文件是多个,则在每一行输出之前加上文件名。 语法: grep 选项 查找模式 文件名1,文件名2, egrep 选项 查找模式 文件名1, fgrep 选项 查找模式 文件名1,,1.grep,grep的一般形式: grep选项基本正则表达式文件 注:基本正则表达式可为字符串。,双引号引用,在grep命令中输入字符串参数时,最好使用双引号括起来。例如: “my string” “jet plane” 这样做有两个原因: 是以防被误解为Shell命令; 可以用来查找多个单词组成的字符串。,在使用变量时也应该使用双引号;在使用模式匹配时,应使用单引号。 注: 由单
30、引号括起来的字符都作为普通字符出现。特殊字符用单引号括起来以后,也会失去原有意义,而只作为普通字符解释。 由双引号括起来的字符,除$、和”这几个字符仍是特殊字符并保留其特殊功能外,其余字符仍作为普通字符对待。,grep选项,常用的选项有: -c 只显示匹配行的数量。 -i 比较时不区分大小写,只适用于单字符。 -h 在查找多个文件时,指示grep不要将文件名加入到输出之前。 -n 在输出前加上匹配串所在行的行号(文件首行行号为1)。 -v 只显示不包含匹配串的行。 grep可以查询多个文件。例如:在当前目录下所有的.doc文件中查询字符串“sort”。方法如下: $grep “sort” *.
31、doc,data.f的记录结构,$cat data.f 48 Dec 3BC1997 LPSX 68.00 LVX2A 138 483 Sept 5AP1996 USP 65.00 LVX2C 189 47 Oct 3ZL1998 LPSX 43.00 KVM9D 512 219 dec 2cc1999 CAD 23.00 PLV2C 68 484 nov 7PL1996 CAD 49.00 PLV2C 234 483 may 5PA1998 USP 37.00 KVM9D 644 216 Sept 3ZL1998 USP 86.00 KVM9E 234,城市位置编号,月份,存储代码及出库年份
32、,产品代号,产品统一标价,标识号,合格数量,行匹配,$grep c “48” data.f $4 要显示包含“48”的字符串的4行文本: $grep “48” data.f 48 Dec 3BC1997 LPSX 68.00 LVX2A 138 483 Sept 5AP1996 USP 65.00 LVX2C 189 484 nov 7PL1996 CAD 49.00 PLV2C 234 483 may 5PA1998 USP 37.00 KVM9D 644,行数,显示满足匹配模式的所有行行数: $ grep n “48” data.f 1:48 Dec 3BC1997 LPSX 68.00
33、LVX2A 138 2:483 Sept 5AP1996 USP 65.00 LVX2C 189 5:484 nov 7PL1996 CAD 49.00 PLV2C 234 6:483 may 5PA1998 USP 37.00 KVM9D 644,显示非匹配行,显示所有不包含“48”的各行。 $ grep v “48” data.f 47 Oct 3ZL1998 LPSX 43.00 KVM9D 512 219 dec 2cc1999 CAD 23.00 PLV2C 68 216 Sept 3ZL1998 USP 86.00 KVM9E 234,精确匹配,精确地抽取只包含“48”的各行。操作
34、如下: $ grep “48” data.f 48 Dec 3BC1997 LPSX 68.00 LVX2A 138 另外一种方法是在抽取字符串后加上 $ grep “48” data.f,大小写敏感,缺省的情况下,grep是大小写敏感的。要查询大小写不敏感字符串,必须使用-i开关。 例如: $ grep -i “sept” data.f,2.grep和正则表达式,模式范围 假如要抽取代码为“483”和“484”的城市,前面讲到可使用 来指定字符串范围。 $grep 4834 data.f,不匹配行首,如果要抽取记录,使其行首不是“48”,可以在 中使用记号。同时在方括号的前面也需要使用表示查询在行首开始。 $grep 48 data.f,设置大小写,使用-i开关可以屏蔽月份sept的大小写敏感,也可以用另一种方式。可以使用 模式抽取各行包含sept和Sept的所有的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 市政广场绿化设计与施工合同
- 洗浴中心招投标授权委托书模板
- 网约车驾驶员服务协议
- 南京市摄影基地租赁合同
- 环保旅游业PTR管理办法
- 城市绿化带扩建合同
- 文化艺术兼职演员合同
- 建筑材料市场租赁合同终止
- 图书馆围墙建设合同
- 人力资源成品油市场管理办法
- 仓储物流安全隐患排查表-附带法规依据
- 新概念英语第二册课文(全中文)
- DB32T 4031-2021 建筑垃圾填筑路基设计与施工技术规范
- 湖南省药品零售企业药店药房名单目录
- DB4401-T 10.5-2019 +反恐怖防范管理++第5部分:教育机构-(高清现行)
- 广东深圳市福田区选用机关事业单位辅助人员和社区专职工作者365人模拟试卷【共500题附答案解析】
- 尿毒症脑病课件
- 小学体育与健康人教二年级全一册第一部分课程目标与教学内容设计构想体育教学设计武术
- 广告制作技术方案
- 煤矿通风系统现状及智能通风系统设计
- 加氢裂化 精品课件
评论
0/150
提交评论