Advertisement

COMP9044/2041 Software Construction: Techniques and Tools 22_T2笔记

阅读量:

Week01 Regular Expression

"中可以使用变量,在' '中则不允许使用变量。无论是单引号还是双引号的功能都是为了包围特殊字符的作用域。

常规的正则表达式通过方括号[]来表示字符列表这一术语称为字符集。
注释表明无需在每个特定符号前重复使用反斜杠\^符号。
例如[^ab]这一模式会匹配除a或b之外的所有单个字符。
特别地:
若不需考虑\^符号,则对应的正则表达式为[^^]其中第一个\^表示非匹配而第二个\^表示该特定符号本身。
若不需考虑\^\backslash这两个特殊符号,则对应的正则表达式应写作[^^\ ]其中第一个\backslash起转义作用而第二个\backslash$直接表示该特殊符号。

这些重定向符均用于将执行结果引导至特定位置。例如:

  • 使用scriptname > filename可将脚本执行结果直接写入指定文檔,并会覆盖文檔中原有的內容
  • 通过使用command &> filename可将标准輸出與標準錯誤均redirect至文檔。
  • 使用>> scriptname > filename, 可實現將standard output與standard errorredirect至不同文檔的效果。
  • 命令command >&2則可將standard output與standard error全部redirect至指定文檔。
  • 則是說,

scriptname >> filename

這種情況下,

使用scriptname >> filename

可將脚本執行結果附加到指定文檔末尾(此種方式不會覆蓋已存在的內容),從而確保新增內容位於现有數據之后。

  • 最後还需要強調的是,

< < used for Here Document,

< < < used for Here String。 ### Here Document 一种Here Document相当于包含特定功能的代码片段。它的官方名称被定义为`嵌入式文档`(简称HereDoc) 该技术通过I/O重定向技术将一系列命令传递至人机交互界面(例如FTP、cat或文本编辑器)。这种方式特别适合在脚本中插入少量多行数据。 建议避免将大块的数据直接嵌入到脚本中;这样做虽然有效但存在明显的局限性。 为了保持代码逻辑与输入数据的独立性最好将它们分别存储在不同的文件中;除非处理的是一个小规模的数据集。 Here Document 的基本用法是: ``` cmd << EOF document1 document2 ... documentN # 文件的内容 EOF ``` 其中 `cmd` 是 shell 命令的一种实现形式,在编程实践中具有重要价值。其中 `<<`, 被视为一种特殊的重定向引导标记,在编程语言中常用于 HereDocument 标识符的操作。其后的内容即被视为 HereDocument 标识符所指定的部分,并在程序执行过程中按照特定规则进行处理。当 HereDocument 结构完成时,在其前后均需附加 `EOF`, 这一标识符的作用即是区分不同 HereDocument 区块的内容边界。值得注意的是, 该标识符并不固定, 开发者可以根据实际需求将其替换为其他符号或字符串表示形式, 这样可以在同一程序中灵活地定义多个独立的信息块进行统一管理与引用操作。具体而言, 位于两个 EOF 符号之间的代码片段会被直接作为输入传递给当前 shell 命令 `cmd`, 从而完成相应的数据处理流程。 `EOF`作为一个tag,可以被替换成任意字符串。tag之后的内容会作为前面的shell命令需要处理的数据,直到再次遇见顶格写、独占一行的tag为止。因此我们需要注意: 1. 用于标识文件结束处的tag必须居左对齐并与其它内容分开一行。 2. 在Here Document环境中同样可以插入tag标记符,在这种情况下必须确保这些tag不居左对齐且各自占据独立的一行。 举个栗子: ``` $ cat < COMP9044 > 22T2 > END COMP9044 22T2 ``` #### 忽略命令替换 通常情况下,在正文中出现的变量和命令也会被进行评估或执行。当 Shell 接收到输入时,在替换之后会将这些变量和命令传递给指定的 command 进行处理。请看以下具体示例:假设我们有一个简单的脚本文件 script.sh,并希望在其中引用一个外部函数 func() 来实现某种功能,则可以在 script.sh 的适当位置插入调用该函数的语句,并确保脚本能够正确运行并生成预期的结果。 ``` $ courseID=COMP9044 $ name=Software Construction: Techniques and Tools $ cat < ${courseID} is ${name}. > END COMP9044 is Software Construction: Techniques and Tools. ``` 用单引号或双引号将分解符包裹起来可以使shell中的变量替换失效 ``` $ courseID=COMP9044 $ name=Software Construction: Techniques and Tools $ cat <<’END‘ > ${courseID} is ${name}. > END ${courseID} is ${name}. ``` #### 忽略制表符 通过将`<<`替换为`<<-`的方式可以在Here Document的所有顶格位置删除Tab键(但不包括空格)。为此我们采用这一方法来实现缩进控制。值得留意的是以下示例及其运行结果,在hello与world前后分别添加Tab与Space以验证效果。 以下是具体示例: - 示例1中,在hello前面添加了两个空格及一个Tab,在world前面添加了两个空格及一个Tab - 示例2中,在hello后面添加了两个空格,在world后面也添加了两个空格 - 示例3中,在hello前面仅添加了一个Tab,在world前面也仅添加了一个Tab - 示例4中,在hello后面仅添加了一个Tab,在world后面也仅添加了一个Tab ``` $ cat testhere.sh #!/bin/sh echo "## test space with <<-" cat <<- EOF hello # 2 spaces before hello world # 2 spaces and 1 tab before world EOF echo "## test space with <<-" cat <<- EOF hello world EOF echo "## test tab with <<- " cat <<- EOF hello world EOF echo "## test tab with <<- " cat <<- EOF hello world EOF ``` 执行的结果如下: ``` $ sh testhere.sh ## test space with <<- hello world ## test space with <<- hello world ## test tab with <<- hello world ## test tab with <<- hello world ``` 可以看到唯一起作用的是第3个例子,顶格的tab被删除了。 ### Here String 在 bash, ksh 和 zsh 中,还可以使用 Here String: ``` $ tr a-z A-Z <<<"Yes it is a string" YES IT IS A STRING ``` 此时也可以使用变量: ``` $ tr a-z A-Z <<<"$var" ``` * * * Ref: 1. [你是如何学会正则表达式的?](https://www.zhihu.com/question/48219401/answer/742444326) ## Week 02 ### sed - Stream EDitor sed 命令最初由 AT&T 开发,并为 Unix 7.0 系统设计。随着 Unix 和 Linux 的发展,在大多数Unix 和 Linux 系统中都能找到其身影。作为一个 强大的文本流处理工具, sed 不需要建立一个图形化的工作区来显示文件内容, 而是直接在终端窗口中进行操作而不依赖于外部可视化界面。通过接收并解析终端输入的一系列指令来执行操作, 它能够逐行对文件进行编辑和修改, 这种方式避免了传统文本编辑器需要先打开视觉缓冲区的问题。 ``` $ sed --options [optional SCRIPT] [INPUT FILE or STREAM] ``` 在sed指针模式下运行命令时会启用增强型(现代)正则表达式的语法特性,默认情况下会使用基本正则表达式(BRE)。若未带此选项,则系统将常规正则表达式转换为增强型(现代)正则表达式;而如果使用了此选项,则会采用基本正则表达式(BRE)。基本正则表达式(BRE)似乎无法用`\.*`来表示任意字符的零次或多次出现。 2. `-e`后跟随 `script` 参数,`-e`的含义是:将其后的`script`参数添加至待执行指令,一条sed指令中可以多次出现`-e` 3. 常见的误区是:`-e`表示支持基础正则表达式,而`-E`表示支持高级正则表达式。 实际上:是否支持高级正则表达式仅由`-E`控制,`-e`与支持正则表达式的版本无关,它的作用相当于append command to be executed,`-e`与`-E`甚至可以同时出现。 举个栗子:当我们想把input.txt中所有的A替换成dddd,且将所有的B也替换成dddd时,下面几种写法是合法的 ``` sed -e 's/A/dddd/g' -e 's/B/dddd/g' input.txt sed -E 's/(A|B)/dddd/g' input.txt sed -Ee 's/(A|B)/dddd/g' input.txt ``` 你可以向 sed 发出一系列不同的命令,用分号(;)分开。 ## Week03 Shell Programming 1. [Shell Style Guide](https://google.github.io/styleguide/shellguide.html) 2. 没有空格 没有空格 给变量命名:在代码块内采用`variable_name=variable_value`的方式进行赋值操作;为避免赋值符号前后出现空格导致的代码错误,在赋值操作中应当确保等号前后直接连接;在编程语言中推荐采用$variable_name或${variable_name}的方式引用变量(其中大括号的存在有助于减少命名冲突的可能性) 3. `$变量1 = $变量2`是在判断两个变量是否相等 `变量1=$变量2`是将变量2的值赋给变量1 4. 在Debian系统的bash终端中(即dash终端),当使用`echo`指令并在单引号括起来的内容时,默认无法进行内容解析;若要实现这一功能,则需在命令后添加`-e`参数(即指定执行模式)。而Mac上的zsh默认会对括号内的内容进行解析,并无需使用特定选项 5. `test $# = 1`与`[ $# = 1 ]`是等价的,注意用`[]`代替`test`时,方括号和判断语句之间要有空格 6. 相较于其他两种写法,在此建议采用$[[ \ldots ]]$形式。该代码块结构通过减少路径名扩展或词分割的方式降低了潜在错误。值得注意的是,在这种结构中,默认支持正则表达式的匹配功能。与之相比,在传统Markdown中,默认情况下不允许进行正则表达式的匹配。 ![在这里插入图片描述](https://ad.itadn.com/c/weblog/blog-img/images/2025-04-22/3BiRgLpY65Z0P4nEy9UsCtexfNwK.png) 7. 我们称其为一个废品收集器,并可将无需处理的数据直接发送至该位置,在此位置会定期清除所有数据 8. 使用{}括起来的代码能够执行shell命令以切换工作目录 9. bash与dash:dash就是Debian Almquist Shell,是bash的精简版。 10. 在Shell脚本的第一行:可以使用`\#! /bin/bash`指定了该脚本将使用Bash进行运行;或者通过设置首行为`\#! /bin/dash`来指定该脚本将使用Dash进行运行。\n若首行为`\#! /bin/sh`时,在不同系统下可能会分别被解释为Bash或Dash脚本;例如,在VLab环境中 ## Week04 1. BRE, ERE, PCRE * 基础的正则表达式(BRE - Basic Regular Expression),遵循 posix 标准定义,用于统一历史上混乱的正则实现。 ERE * * 增强型正则表达式(ERE),遵循 posix 标准定义,在弥补 BRE 的不足的同时新增了功能。 * Perl 兼容型正则表达式(PCRE),源于 perl 语言的发展,并被移植至多种平台及编程语言中。 * 主流 编程 语言 如 Java 和 Python 中的 正 则 实 现 大 多 基 于 PCRE。由于 PCRE 的 强 大 功 能 显 著 超 越 了 BRE 和 ERE,在这一领域占主导地位。尽管如此 ,大 多 数 同 学 只 了 解 其 基 础 部 分 。 以上三种 规 则 的 区 别 见 https://juejin.cn/post/7011652542383783950 2. 在 PCRE 规则体系下采用 `\d` 表示数字模式不适合用于 sed 和 grep 等命令(仅限于 BRE 和 ERE 格式)。对于 sed 和 grep 等命令来说,在需要匹配数字时应当采用 `[0-9]*` 模式。 3. `statement1 && statement2`: 依次执行 statement1 和 statement2 4. 在 /etc/passwd 文件中搜索 "bin" 这个词时,默认情况下 `grep 'bin' /etc/passwd` 不仅有 bin 匹配还会包含 sbin 或 bing 等类似名称的行。 如果要精确匹配 bin 这个词而不包含 sbin 或 bing 的话,则应采用 `grep '\' /etc/passwd`。这样我们通过使用 < 和 > 来准确限定 bin 这个词的匹配范围而不是将其纳入 sbun 或 bun 类别。 此外还可以借助 -w 选项达到相同目的 ## Week 07 1. [浅谈 _args和**kwargs与解包运算符_]() ## Week 08 ### Test 08 该内置函数允许指定自定义键值来实现灵活多样的排序逻辑,默认情况下会按照元素自身的属性进行排列(若需自定义则需指定相应的键值)。该方法会对原有列表进行操作并直接修改其顺序(不会产生新列表),操作完成后原有列表的内容会随之调整但无返回结果生成。 `sorted()`函数则提供了一种更为便捷的方式,在不影响原始数据完整性和可用性的前提下完成数据排列任务(返回值为新的有序序列)。这种做法特别适合需要后续继续操作原始数据的情况。 值得注意的是,在这两种方法中,“key”参数均支持传递匿名函数(如lambda表达式)作为参数之一(即参数索引位置为1),以此实现更为复杂的多条件排序需求。具体而言,在实际应用中,默认情况下,“key”参数未设置时会按照元素本身的属性进行排列(若需自定义则需指定相应的键值)。例如: 假设我们有如下学生数据: [ {'id': 101, 'name': 'Alice', 'age': 20}, {'id': 102, 'name': 'Bob', 'age': 25} ] 那么通过调用上述两种方法分别对其进行年龄从低到高、然后姓氏从A到Z的双重排序即可得到预期结果。 ``` >>> students = [[3,'Jack',12],[2,'Rose',13],[1,'Tom',10],[5,'Sam',12],[4,'Joy',12]] >>> new_students = sorted(students, key=lambda x:(x[2],x[1])) >>> new_students [[1, 'Tom', 10], [3, 'Jack', 12], [4, 'Joy', 12], [5, 'Sam', 12], [2, 'Rose', 13]] >>> students [[3, 'Jack', 12], [2, 'Rose', 13], [1, 'Tom', 10], [5, 'Sam', 12], [4, 'Joy', 12]] >>> students.sort(key=lambda s:(s[2],s[1])) >>> students [[1, 'Tom', 10], [3, 'Jack', 12], [4, 'Joy', 12], [5, 'Sam', 12], [2, 'Rose', 13]] ``` * * * Python中的lambda是一种语法结构,它具备三类特性,能够实现四类应用场景,同时这一技术在应用过程中也存在一定的争议

全部评论 (0)

还没有任何评论哟~