Date:2021-5-30
Author:Sid
5月25日的课上,老师使用的ORCHIDEE自动化脚本中出现了emplace()
函数,这个函数到底做了什么?遵循了什么语法?在这里分析一下。以及是否有其他。
首先是老师的代码
xxxxxxxxxx
81remplace()
2{
3sed "/$1/D" run.def > r2
4cat <<END >>r2
5$1=$2
6END
7mv r2 run.def
8}
涉及的基础知识有:
sed
命令的使用cat
命令的使用开始之前需要知道:
$
来表示命令提示符,表示后面的内容需要在命令行环境下输入。开头没有$
表示这行内容是shell脚本中的代码。#
开始为注释。<something>
用尖括号表示的部分是命令中需要替换的部分,连尖括号一起换成想要输入的内容。$1
和$2
分别是传入函数的第一个和第二个变量。
在rinscript.sh
脚本中,调用remplace
函数时的代码是:
xxxxxxxxxx
11remplace RESTART_FILEIN NONE
对应的RESTART_FILEIN
就是传入remplace
函数的的第一个变量$1
,NONE
就是传入的第二个变量$2
(上例此处是空值)
还有其他的传入变量,如$0
是执行脚本的文件名。了解更多Shell的传入变量可以看菜鸟教程Shell 传递参数,变量的创建、修改和调用可以看菜鸟教程:Shell 变量。
sed
命令sed
命令是一个以行为单位处理文本的命令。原函数中还有>>r2
,这是数据流重定向的内容,后面会写。
xxxxxxxxxx
11sed "/$1/D" run.def
上面这段代码是使用sed
函数,将run.def
中含有变量$1
的这一行给删掉了,并将结果输出。
remplace函数中,引号内表示对行内容进行怎样的操作,"/$1/D"
表示:
$1
传入的字符串的那一行(先定位)D
表示删除操作(再操作)上例中紧接着的run.def
表示sed
命令是从这个文件读入数据的,处理的是run.def
文件的内容,并将数据输出到standard output。在没有设定的情况下是输出到屏幕,但是函数中在行末还加上了> r2
,这就进行了数据流重定向,standard output的内容输出到了r2文件中,没有输出到屏幕。
sed
命令的功能很多很强大,老师在这里的写法也有些特殊。这里使用D
和d
实现的功能是相同的,但是D
涉及到pattern space中newline的问题,这里其实用不到,d
够用了。
sed
的常见用法菜鸟教程:sed命令就够用,详细用法建议使用info命令查看:
xxxxxxxxxx
21# 查看sed的帮助手册
2$ info sed
前面我们提到了standard input 和standard output,命令会从standard input中读入数据,并输出数据到standard output。在没有专门设定的时候,standard input是从键盘读入,standard output是输出到屏幕。但有时候在脚本中,我们没法从键盘读入,又需要输出数据到文件,这时候就可以用重定向来设定standart input/ouput的来源和去向。
xxxxxxxxxx
11sed "/$1/D" run.def > r2
>
和>>
设定了standard output的去向。remplace
函数中> r2
就是将sed
输出到standard output的内容从屏幕重定向到了r2
文件,本来输出到屏幕,现在改成了r2
。而>
和>>
的区别是,前者会创建一个新文件,并储存输出的内容;后者会检测这个文件是否已存在,如果存在输出的内容会累加到这个文件的最后,如果不存在的话会新建文件并储存输出的内容。
xxxxxxxxxx
11cat <<END >>r2
所以脚本中 >>r2
就是将cat
命令的standard output重定向到了r2
,而且是以累加的形式添加到r2
文件上的。
<
可以设定standard input的来源,使得从键盘获取输入的命令也能从文件获取输入。
xxxxxxxxxx
31$ cat < <filename>
2# for example
3$ cat < /etc/issue
而<<
虽然长的和<
很像,但它不属于数据流重定向,而是here documents的知识点。在cat
命令的使用部分会讲。
cat
命令的使用示例:
xxxxxxxxxx
91$ cat <filename>
2# Example1
3$ cat /etc/issue
4
5#Example2:
6# cat without specific file
7$ cat
8<input anything>
9# 然后按ctrl + D 结束输入
例1中,输入命令并回车后,会在屏幕上看到/etc/issure
这个文件的内容。
例2中,输入命令后,会发现命令提示符消失了,此时你能够通过键盘输入,并能在屏幕上看到输入结果。但此时会发现无法停止输入的状态,回车变成了换行而不再具有执行命令的功能。此时你需要做的是ctrl
+D
来结束输入。
类似的,命令行中用ctrl
+D
可以结束输入。(还有一个ctrl
+C
能够中止命令执行,也很好用。)
中cat
是像例2一样,没有指定文件,需要standard input,就是下一行的$1=$2
。remplace函数脚本执行的时候是不需要按ctrl
+D
的,那如何结束输入状态呢?、
这就用到here document,脚本是通过<<
和END
来实现。第一个<<
设定了中止输入的字符,后续的内容都作为standard input,直到输入了<<
后面紧跟的字符后,就相当于按下了ctrl
+D
,停止了输入状态1。
>>r2
是数据流重定向,经测试发现 <<
和>>
的先后顺序是没有影响的。
xxxxxxxxxx
31cat <<END >>r2
2$1=$2
3END
remplace
函数回头看看remplace函数做了什么呢?
xxxxxxxxxx
81remplace()
2{
3sed "/$1/D" run.def > r2
4cat <<END >>r2
5$1=$2
6END
7mv r2 run.def
8}
run.def
中要修改的行删掉,并输出到r2
文件r2
文件的最后r2
文件重命名为run.def
文件同样的功能还能通过哪些方法实现呢?
xxxxxxxxxx
211# Example 1
2remplace()
3{
4sed '/$1/d' run.def > r2
5echo "$1=$2" >> r2
6mv r2 run.def
7}
8
9
10#Example 2
11remplace()
12{
13sed -i "/$1/d;\$a $1=$2" run.def
14}
15
16#Example 3
17remplace()
18{
19sed -i "/$1/c $1=$2" run.def
20}
21
欢迎通过邮件和我交流cnqdcyq@163.com