美文网首页
Linux/Shell脚本学习笔记【持续更新】

Linux/Shell脚本学习笔记【持续更新】

作者: IWW_luck | 来源:发表于2020-11-19 13:50 被阅读0次

    最近在读机械工业出版社的《shell脚本学习指南》,不得不说单纯看书中的语法真的很晦涩难懂,还是结合常见应用场景和案例对比来学习吧!毕竟学也是为了更好的用嘛。

    另,这里把学习过程中遇到的一些常见、好用的记录下来,方便以后回顾。毕竟编程语言和框架那么多,程序员是不可能时时刻刻把所有的语法和代码写法记在脑子里滴,知道能靠什么工具实现比较重要。况且在shell命令使用过程中,还有--help来帮忙,能给我们提供比较详尽的介绍。

    一、Bash Shell

    二、正则表达式 RE

    三、Shell命令——文本神器三兄弟 awk,grep,sed

    四、其他Shell命令

    五、shell例题

    六、参考资料


    一、Bash Shell

    1.bash Shell中的元字符:

    bash Shell本身不支持正则表达式,使用正则表达式的是Shell命令和工具,例如grep、awk、sed等。但是bash Shell可以使用正则表达式中的一些元字符实现通配功能。这些元字符在通配中的意义与正则表达式中的意义不完全一致,如下所示;

    * 表示——任意位的任意字符,而与前面的字母无关。这里和正则表达式的*对比一下,正则表达式中,*往往用于表达前面一个普通字符的0次或者多次重复。由此可见Shell元字符和正则元字符的不同。

    ? 表示——一个任意字符^表示——取反[]表示——字母集合(与正则中一样)

    {}表示——一组表达式的集合·command·相当于$(command),用于进行命令替换,command为shell命令。(注:·是tab上方的反撇号,在这里编辑出来长得和shell中不同)${variable}相当于$variable,用于进行变量替换,variable表示shell变量。一般来说${variable}和$variable是一样的,只是${variable]在表达变量名的界限时更清晰。除此之外,${variable}还可以用于剪切或取变量的局部等。$[]与$(())用于进行数学计算。

    2.管道和重定向:

    【用法差异】

    管道 —— command 1 | command 2 | command 3 左边的命令有标准输入,右边的命令接受标准输出

    它仅能处理经由前面一个指令传出的正确输出信息,也就是 standard output 的信息,对于 stdandard error 信息没有直接处理能力。然后,传递给下一个命令,作为标准的输入 standard input.。

    重定向 —— 

    command1 < file1 左边的命令需要标准输入,右边只能是文件

    command1 > file2 左边的命令有标准输出,右边只能是文件

    【进程差异】

    管道触发两个子进程执行|两边的程序;

    重定向是在一个进程内执行

    3.转义符:

    转义符可以使得元字符被解析为字面含义,共有三种,反斜杠,双引号,以及单引号。三种的转义程度不尽相同。

    ' '单引号,不具有变量置换(解析)功能($变为纯文本);硬转义,其内部所有的shell 元字符、通配符都会被关掉。

    " " 双引号,具有变量置换(解析)功能($可保留相关功能);软转义,其内部只允许出现特定的shell 元字符

    \跳脱字符,将特殊字符或者通配符还原成一般字符

    3.1 反斜杠 \ ——去除其后紧跟的元字符或通配符的特殊意义。

    3.2 双引号 "" ——又称软转义,其内部只允许出现特定的shell 元字符

    3.3 单引号 ‘ ’ ——又称硬转义,其内部所有的shell 元字符、通配符都会被关掉。注意,硬转义中不允许出现单引号。

    二、正则表达式RE 

    1.正则表达式的元字符:

    这一小节着重讲解正则表达式,因为正则表达式是UNIX工具使用和构建模型上的基础,值得花时间学习并在练习中不断熟悉它。

    正则表达式区分BRE以及ERE共两种模式,正则表达式由一般字符和元字符组成。BRE和ERE的元字符稍有不同,如下所示:

    【BRE】&【ERE】共享的元字符:

    \——用于关闭后续字符的特殊意义。或者用\{...\}

    *——用于匹配前面一个普通字符的0次或者多次重复。对于ERE来说,*的前置字符可以是正则表达式,例如.*带表“匹配任一字符的任意长度”

    .——用于匹配任意单个字符

    ^——表示匹配紧接着的正则表达式。(文本匹配锚点)

    $——匹配前面的正则表达式。(文本匹配锚点)

    []——匹配方括号内的任一字符。

    【BRE】

    \{n\}——匹配前面字符出现n次,如[a-z]\{5\}表示精确匹配5个小写英文字母

    \{n,\}——匹配前面字符至少出现n次

    \{n,m\}——区间表达式。匹配前面字符出现n--m次

    \(  \)...\n —— \(与\)之间的模式存储在特殊的保留空间,最多可以将9个独立的自模式存储在单个模式中。子模式可通过转义序列\1至\9,被重复使用在相同模式中,\n指的是“匹配于第n个先前方括号内子表达式匹配成功的字符”。如\(ab\).*\1指的是匹配于ab组合的两次重现,中间可存在任何数目的字符。如\(ab\)\(cd\)[def]*\2\1表达的是abcd...cdab,中间可以是def字符集合的任意组合,故可以匹配的最小字符串是abcdcdab,还可以匹配abcdeeecdab,abcdddeeffcdab。这种机制是BRE提供的后向引用机制,指的是“匹配于正则表达式匹配的先前的部分”。在ERE里,\(..\)不表示后向引用,匹配的是字面上的左括号和右括号。

    【ERE】—— 正则表达式的扩展

    {}——区间表达式,表示匹配前面的单个字符重现的次数区间。不需要反斜杠。

    ? ——匹配?之前的正则表达式0次或者1次,如JO?B可以匹配JOB,JOOB

    + ——匹配+之前的正则表达式1次或者多次,如S+EU可以匹配SSEU,SSSEU等,但不可以表示SEU因为此处的+至少匹配一个S

    |——表示或者,匹配|之前或者之后的正则表达式

    【正则表达式的扩展】

    \<  \>分别匹配单词word的开头和结尾。例如/<chop可以匹配use chopsticks而不能匹配eat a lambchop,chop/>可以匹配eat a lambchop而不能匹配 use chopsticks, /<chop/>则既无法匹配use chopsticks又无法匹配eat a lambchop

    【UNIX程序及其正则表达式类型】

    grep: BRE,\<  \>

    sed: BRE,\<  \>

    ed: BRE,\<  \>

    ex/vi: BRE,\<  \>

    more: BRE,\<  \>

    egrep:ERE

    awk:ERE

    lex:ERE

    记住我们的Linux三剑客,sed, awk,grep,他们所支持的正则是不同的哦。

    注意:横杠字符“-”虽然不是正则表达式的元字符,但由于横杆字符是引出命令选项的特殊字符,所以需要用引号和转义符来表示。例如,想要在1.txt文件中找到以“-----”连续五个横杠符号开头的字符串,应该使用以下的命令

    grep "\-\{5\}" 1.txt

    那么“-----”可不可以呢?答案是不可以。无论你是用"\-\{5\}"还是"\-\-\-\-\-"来表示连续5个“-”,反斜杠转义符都是少不了的。预知原因为何,请看第3小点转义符中相关说明。


    三、Shell命令——文本神器三兄弟 awk,grep,sed

    grep

    grep家族有三兄弟:grep , fgrep , egrep

    grep: 标准

    egrep:扩展grep命令,支持正则表达式(基本和扩展),等价于grep -E

    fgrep:快速grep命令,不支持正则表达式,按照字符串的字面意思进行匹配,等价于grep -F

    一般来说,egrep和fgrep极少使用

    awk

    awk是一种能对结构化数据进行操作,并产生格式化报表的工具

    sed

    非交互式文本编辑器,可对文本文件和标准输入(键盘输入、文件重定向、字符串、变量or来自管道的文本)进行编辑(输出、插入、删除、替换等)

    sed只是对缓冲区中原始文件的副本进行编辑,不编辑原本的文件

    sed调用方式

    (1)在Shell命令行输入命令调用sed:

    sed 'sed-command' input-file>result-file 

    (2)将sed命令插入脚本文件之后,通过sed命令调用它

    sed -f sed脚本文件 input-file

    -f表示正在调用sed脚本文件

    (3)将sed命令插入脚本文件之后,设置该脚本文件为可执行,然后直接执行该脚本。(这种方式的sed脚本文件需要以sha-bang(#!)开头)

    ./sed脚本文件 input-file

    sed命令的组成

    一般由定位文本行和sed编辑命令(可以放在单引号内或者单引号外)两部分组成,sed提供两种方式定位文本:

    (a)使用行号,指定一行,或者指定行号范围

    (b)使用正则表达式

    sed编程的栗子🌰

    四、其他Shell命令

    1. find

    2.sort 排序

    3.uniq 去重【sort和uniq经常配套使用,毕竟生活中许多统计场景都需要去重、排序、统计频率等操作】

    4.head和tail

    比较常见的用法是head -n file.txt和tail -n file.txt,用于取file.txt文件的前n行和后n行

    次常见且比较灵巧的用法还有 head -n-10 file.txt和tail -n+10 file.txt等

    前者代表除了最后10行数据之外,显示其余所有内容。【排除后十行】

    后者代表从文本文件第10行开始,取其后部。【从第十行开始】

    五、Shell例题

    【例1】习题:leetcode 195 《第十行》

    给定一个文本文件 file.txt,请只打印这个文件中的第十行。

    示例:

    假设 file.txt 有如下内容:

    Line 1

    Line 2

    Line 3

    Line 4

    Line 5

    Line 6

    Line 7

    Line 8

    Line 9

    Line 10

    你的脚本应当显示第十行:Line 10

    链接:https://leetcode-cn.com/problems/tenth-line

    方法一:借用python (比较trick的一个写法,适合shell救急)

    方法二:head tail大法好

    对于tail和head的使用,有两种思路:

    一种是取前十行的最后一行head -10 file.txt|tail -1,这种思路需要考虑文件的实际行数

    若超过十行,则可直接取最后一行,即为第十行( head+tail 夹逼法)

    若不超过十行,直接对head -10 file.txt做tail操作实际上取到的是第6、7、8、9行(视file.txt实际行数而定)

    另一种是取从第十行开始的内容,取其第一行。这种思路无需对总行数小于10的情况做检验,会自动返回空字符串,符合题目要求。

    tail -n+10 file.txt|head -1

    方法三:巧用awk sed

    摘抄力扣大佬答案

    -n选项表示:不打印sed编辑对象的全部内容

    【例2】

    grep "([0-9]\{3\})" number.txt 不含转义标志"\","("与")"直接匹配中字符串"(234)"中的双括号

    grep "\([0-9]\{3\}\)" number.txt 含转义字符,不参与字符匹配

    练习题:详见leetcode 193 有效电话号码

    六、参考资料

    1、Leetcode    https://leetcode-cn.com/

    2、OSCHINA    https://my.oschina.net/badboy2/blog/478953

    3、 《Shell脚本学习指南》机械工业出版社

    相关文章

      网友评论

          本文标题:Linux/Shell脚本学习笔记【持续更新】

          本文链接:https://www.haomeiwen.com/subject/fumxiktx.html