Centos7学习笔记(十六)- 正则表达式高级部分

1、正则表达式工作流程

  1. 取得正则字符串并检查正则语法。

  2. 编译:将正则字符串编译成真正的正则表达式。

  3. 启动正则引擎开始匹配

正则引擎:逐个字符扫描字符串并与编译后的正则表达式的各个元素进行匹配。

何为正则元素呢?

  • 纯字符组合,比如“abc123”,那么每一个字符都是一个正则元素

  • [a-z]这样的样式,那么视中括号[]为一个整体作为正则元素,中括号内的内容是限定的匹配范围

  • 字符匹配的反斜线序列也是一种正则元素

  • 字符.是一个独立的正则元素,它除了不能匹配\n,其他任意字符都能匹配

  • 所有的*、?、{m}、{m,}、{m,n}、{,n}这几个正则,都是作为量词存在的,即计量数量,这些量词,不能作为独立的正则元素,但是是作为修饰符存在,修饰定义它前面的字符或子表达式内容。

  • |分隔符两端的,比如a|b这样的表达,那么竖线两端的字符或子表达式都是正则元素

  • ()圆括号将视为一个整体正则元素,比如sed中常用的(.*)。

2、正则表达式匹配流程

正则是按每一轮的方式匹配,每轮,都要从正则的第一个元素从头开始匹配。

即,被匹配的字符串或内容被逐个字符扫描去匹配正则元素,若成功,下一字符匹配下一个正则元素,若不成功,则消耗掉已经被扫描匹配的字符,剩余的字符,进入下一轮完整匹配。

3、正则引擎

DFA类——确定有穷状态机,

    将扫描到的字符与所有可能的分支一次性进行匹配

    不断淘汰匹配失败的分支,最终确定一个成功的分支

    DFA对字符串中的每一个字符,只扫描匹配一次,不会回溯,也没有字符交还的过程

NFA类——非确定有穷状态机

    它对正则表达式中的所有分支做标记,以便匹配失败时,可以根据标记回头匹配其他分支,然后从中选择一个分支优先匹配,剩余分支先放着,在所选分支匹配失败时,再回头选择其他分支

    如果某个分支匹配成功,则剩下的分支就直接丢弃

    它会记录所有可能的分支,每个分支的匹配都是不确定的,失败的时候回头重新匹配其他分支

    NFA有可能在匹配失败后,交还字符,然后回溯,并对某个字符进行多次匹配

DFA、NFA混合类

[root@c7study /home/study/.ssh]# echo '404 not found'|perl -nE '/not|not found/;say $&'           #《========$&是表示匹配的内容
not
[root@c7study /home/study/.ssh]# echo '404 not found'|perl -nE '/not found|not/;say $&'
not found
[root@c7study /home/study/.ssh]# echo '404 not found'|egrep 'not|not found'
404 not found

4、什么是回溯?及影响?

回溯就是在有分支或者贪婪匹配时,为了正确获取匹配结果,必须在分支匹配失败或贪婪匹配内容过多后,交还字符,然后回头重新进行字符扫描匹配。

它的显著影响是很有可能大大降低正则匹配的效率,显著的提高了匹配花费时间。

image.png

5、反斜线序列正则

①字符匹配类

\n——匹配换行符

\N——匹配非换行的字符

\w——匹配单词构成部分,等价于[_[:alnum:]]

\W——匹配非单词构成部分,等价于[^_[:alnum:]]

\s——匹配空白字符,等价于[[:space:]]

\S——匹配非空白字符,等价于[^[:space:]]

\d——匹配数字,等价于[0-9]

\D——匹配数字,等价于[^0-9]

\\——匹配\字符

②位置锚定类

\b——匹配单词边界处(开头和结尾),如\bword\b

\<——匹配单词开头位置

\>——匹配单词结尾位置,所以,\<和\>是配对使用的

\B——匹配非单词边界处的位置

\A——匹配字符串的绝对行首

\z——匹配字符串的绝对行尾

\Z——匹配字符串的行尾,如果行尾有换行符,那么匹配换行符前的位置

\G——第一次匹配的位置,全局匹配有效,也称为位置粘滞

^——匹配每一行行首

$——匹配每一行行尾,换行符前的位置

image.png理解这些位置

那么,^$为啥能匹配空行?看下图就能理解:

image.png图中以字符串abc\n\n123\ndef为例,既符合^又符合$位置的,只有空行那一行。

6、贪婪匹配、非贪婪匹配、占有优先匹配

上述正则元素中解释的作为修饰符存在的量词,是引起贪婪匹配的原因。那么什么是非贪婪匹配和占有优先匹配呢?先看其具体表达

贪婪匹配非贪婪匹配占有优先匹配
**?*+
?
???+
++?++
{m}

{m,}{m,}?{m,}+
{m,n}{m,n}?{m,n}+
{,n}{,n}?{,n}+
  • 非贪婪匹配时,{m}?和{m,n}?是等价的,因为最多都匹配m次。

  • ??在非贪婪匹配时,它匹配任意一个字符、位置、空字符,但这种使用方式基本不会用

  • 在perl中,因为不支持{,n}的方式,所以也没有对应的非贪婪匹配{,n}?和占有优先匹配{,n)+

  • 关于{m},因为它本身是精确匹配,所以{m}?和{m}+也并无意义。

非贪婪匹配,是跟贪婪匹配完全相反的匹配。贪婪匹配是尽可能多的匹配,然后慢慢交还字符,而非贪婪匹配,则是尽可能少的匹配,然后若是不能完全匹配,则逐个消耗匹配成功的字符。

image.png

image.png

占有优先匹配,它是在贪婪匹配的基础上,所有匹配成功的字符都被消耗掉,不会再交还进行回溯。所以,等同于零宽断言。一般而言,占有优先匹配的+后不应有字符,特别是*+这个,它会消耗掉其后的所有字符元素。

7、环视锚定

环视锚定也用于匹配位置,也是一种位置锚定。位置锚定,就不会消耗字符元素。

几种写法:

(?=...)——从左向右顺序环视,这里的...表示要匹配的内容,比如a(?=\d)表示锚定a字符右边开始是数字的情况。

(?!...)——从左向右顺序环视的取反,...仍然表示要匹配的内容,但是要取反内容,比如a(?!\d)表示a字符右边不是数字的情况

(?<=...)——从右向左逆序环视,...表示要匹配的内容,比如(?<=\d)a表示字符a左边是数字的情况匹配成功

(?<!...)——从右向左逆序环视,但是匹配内容取反。比如(?<!\d)表示字符a左边是非数字情况匹配成功

8、分组捕获

分组捕获这个概念,其实就是sed命令中常用的(.*),然后反向引用\1这种形式。用()来把内容视为一个整体,然后“捕获”,并可以引用。

分组捕获后匹配的结果,会被保存在变量中,可以使用\n或$N(perl支持)来取得各分组捕获所匹配的结果。

还有一些分组捕获的方式,主要是在perl中支持。下面来分类解释:

①命名捕获

命名捕获的意思是将捕获匹配的内容,独立命名,使捕获内容既可以传统引用,又可以用命名引用。在引用的时候,可以用传统的\n或$n方式引用,也可以用\k<名字>的方式引用。在正则外部,比如perl中,可以用$+{名字}

使用形式是(?<NAME>pattern)。其中,NAME是要定义的名字,pattern是需捕获内容。

在引用的时候,可以用传统的\n或$n方式引用,也可以用\k<NAME>的方式引用。在正则外部,比如perl中,可以用$+{NAME}来引用。

image.png

②匿名捕获(只分组不捕获)

匿名捕获,即是将匹配内容只是做分组匹配,并不讲匹配内容赋予变量以引用。

使用形式:(?:pattern)

③固化分组

固化分组其功能上跟占有优先匹配(*+、?+、++、{m}+、{m,n}+、{m,}+)是等价的。匹配上了,即占有(占有字符了)了,不交还字符,不回溯了。

固化分组,也是没有捕获功能的。

使用形式:(?>pattern )

image.png

9、匹配模式的修饰符

这里的“修饰符”指的都是perl支持的方式,功能上,更像是一个开关,使原本不能匹配的方式,通过加修饰符,变的能匹配。主要用在编程语言环境,比如perl。因为编程语言环境,允许一个字符串,包含各种特殊的字符,比如\n\t这种。

有如下若干修饰符:

i:作用,忽略大小写

image.png

m:作用,让^和$能匹配含有像\n这样特殊字符的字符串的每一行行首和行尾。(注意:这不是grep、awk、sed这3个按行处理文字内容的常规处理方式)

image.png

s:作用,让.能匹配\n这样的换行符。看下图示例:

image.png

x:作用,允许正则表达式使用空白符号(甚至加#注释),免得使正则表达式晦涩难懂,这称之为free-spacing。在使用x修饰时,会使要匹配处理的内容中原本的空白符号失去意义,这时候,就必须要用\s或者[:space:]去匹配空白符号。

$ans="cat sheep tiger";

$ans =~ /(\w) *(\w) *(\w)/;       # 正常情况下的匹配表达式

$ans =~ /(\w)\s*   (\w)\s*   (\w)/x;

$ans = ~ /

       (\w)\s*      # 可以加上本行注释:匹配第一个单词
       (\w)\s*      # 可以加上本行注释:匹配第二个单词
       (\w)         # 可以加上本行注释:匹配第三个单词
       /x;

$ans =~ /
        (\w)\Q \E   # \Q \E强制将中间的空格当作字面符号被匹配
        (\w)\Q \E
        (\w)
       /x;

o:作用,使正则表达式只被编译一次,编译后的结果被缓存下来,以便循环调用。o修饰符在有循环处理正则的情景中,非常有用,能大大缩减处理时间。如下图中的示例:<br/>

image.png

g:作用,全局匹配。

1、默认情况下,正则匹配会在匹配成功一次后,就退出匹配。(grep是全局匹配的,不算在内)

2、加入g修饰符后,正则匹配会在成功匹配一次后,设置一个指针,该指针位于第一次匹配成功的结果之后。其作用是标记位置,以便下一轮全局匹配从当前标记位开始。如果第2轮或者某一轮全局匹配失败,则默认情况下,该指针会被重置到需匹配的内容(字符串或者文本内容等)的开头。

image.png

3、为了解决上述第二条指针重置的问题,引入c修饰符,使指针在匹配失败后,保持不动,后续全局匹配,能继续处理后续内容。

image.png

4、位置粘滞\G的作用。\G针对全局匹配时使用,要求指针后的内容在下一轮匹配时必须成功,否则指针重置。

image.png

image.png

5、g修饰符,基本都是用在循环结构中,以便重复匹配能够成功。

// 查看全文
2020 9月 16

Centos7学习笔记(十五)- ansible初步

1、安装要求

管理主机:

必须不能是windows系统。类Uinx系统下,python版本为2.6或者2.7。OS X系统,需修改ulimit值才能使用ansible的多子进程。

托管节点:

Python版本不得低于2.4,如果Python版本低于2.4,那么需要安装python-simplejson模块。

2、ansible安装

redhat系需要安装epel源,fedora不用,可以直接安装

yum -y install ansible

(yum -y install libselinux-python,系统如果没这个包,需安装。在被操控主机(托管节点)上,也需要安装此软件,否则与copy/file/template相关的函数将不能使用)

3、基本的文件构成

/etc/ansible/hosts默认主机列表清单文件

/etc/ansible/ansible.cfg默认配置文件

/etc/ansible/roles/角色目录


4、基本的用法——公钥与密码

①公钥指纹的免yes确认。

三种方法:

1)/etc/ansible/ansible.cfg第71行,去除#符,修改为host_key_checking = False

2)/etc/ansible/ansible.cfg第375行,去除改行#注释,修改为

ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no

3)ansible命令执行时,添加--ssh-common-args "-p 52113 -o StrictHostkeyChecking=no"选项。

ansible  -u study -k --ssh-common-args "-p 52113 -o StrictHostKeyChecking=no" -m command -a "df -h" 172.16.1.71
SSH password: 
[WARNING]: sftp transfer mechanism failed on [172.16.1.71]. Use ANSIBLE_DEBUG=1 to see detailed
information
[WARNING]: scp transfer mechanism failed on [172.16.1.71]. Use ANSIBLE_DEBUG=1 to see detailed
information
172.16.1.71 | CHANGED | rc=0 >>
文件系统        容量  已用  可用 已用% 挂载点
devtmpfs        476M     0  476M    0% /dev
tmpfs           487M     0  487M    0% /dev/shm
tmpfs           487M  7.6M  479M    2% /run
tmpfs           487M     0  487M    0% /sys/fs/cgroup
/dev/sda3        28G  2.0G   26G    8% /
/dev/sda1       253M  136M  118M   54% /boot
tmpfs            98M     0   98M    0% /run/user/1000

②免输入密码认证

1)在/etc/ansible/hosts文件中,指定托管主机的ssh_user,ssh_pass,ssh_port等。

image.png

2)密码统一的情况下,可修改/etc/ansible/ansible.cfg中default部分,指定密码。

3)用ssh公钥免密登录方式。


5、基本用法——基本模块

usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]

              [--become-user  BECOME_USER] [-K] [-i INVENTORY] [--list-hosts] [-l SUBSET] [-P

              POLL_INTERVAL]  [-B  SECONDS]  [-o]  [-t   TREE]   [-k]   [--private-key   PRI‐

              VATE_KEY_FILE] [-u REMOTE_USER] [-c CONNECTION] [-T TIMEOUT] [--ssh-common-args

              SSH_COMMON_ARGS]    [--sftp-extra-args    SFTP_EXTRA_ARGS]    [--scp-extra-args

              SCP_EXTRA_ARGS]  [--ssh-extra-args  SSH_EXTRA_ARGS]  [-C] [--syntax-check] [-D]

              [-e  EXTRA_VARS]  [--vault-id  VAULT_IDS]  [--ask-vault-pass  |   --vault-pass‐

              word-file  VAULT_PASSWORD_FILES]  [-f  FORKS]  [-M MODULE_PATH] [--playbook-dir

              BASEDIR] [-a MODULE_ARGS] [-m MODULE_NAME] pattern

ansible-doc -l ——用于列表出所有模块

ansible-doc -s 模块名 ——查看该“模块名”的所有使用参数

①command模块

[root@m01 ~/.ssh]#ansible-doc -s command

- name: Execute commands on targets
  command:
      argv:                  # Passes the command as a list rather than a string. Use `argv' to
                               avoid quoting values that would
                               otherwise be interpreted
                               incorrectly (for example "user
                               name"). Only the string or the
                               list form can be provided, not
                               both.  One or the other must be
                               provided.
      chdir:                 # Change into this directory before running the command.           #《=====相当于cd命令,改变到某目录。用法:-a "chdir=/root ls"
      cmd:                   # The command to run.
      creates:               # A filename or (since 2.0) glob pattern. If it already exists,      #《=======相当于测试[ -e 文件或目录 ],测试成功则不执行后续步骤。
                               this step won't be run.
      free_form:             # The command module takes a free form command to run. There is no    #《======= -a能跟的""里的命令内容,基本都属于free_form.
                               actual parameter named 'free
                               form'.
      removes:               # A filename or (since 2.0) glob pattern. If it already exists,       #《=======跟creates相反,当[ -e 文件或目录 ]成功时,执行后续步骤。
                               this step will be run.
      stdin:                 # Set the stdin of the command directly to the specified value.
      stdin_add_newline:     # If set to `yes', append a newline to stdin data.
      strip_empty_ends:      # Strip empty lines from the end of stdout/stderr in result.
      warn:                  # Enable or disable task warnings.         #《========忽略或显示警告内容,布尔值,范围:0, 'on', 'f', 'false', 1, 'no', 'n', '1', '0', 't', 'y', 'off', 'yes', 'true'

image.png

<br/>

②shell模块<br/>

shell跟command一样,不过shell支持管道等所有特殊字符

③copy模块

常用参数:<br/>

src——要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用"/"来结尾,则只复制目录里的内容,如果没有使用"/"来结尾,则包含目录在内的整个内容全部复制,类似于rsync。

dest——必有参数。文件应被拷贝到的远程绝对路径。如果src是一个目录,dest也必须是目录。<br/>

ower——定义所拥有文件/目录的所属用户名称,类似chown功能<br/>

group——定义所拥有文件/目录的所属用户组名称,类似chown功能

mode——定义文件或目录的权限,等同于chmod,参数可以为“u+rwx or u=rw,g=r,o=r”形式,也可以是数字形式,新版本可以是preserve字串

backup——创建备份文件并包含时间戳信息,以便能够还原回文件,在某种情况下原文件被错误覆盖事。默认是no,可选值为yes、no。<br/>

content——当使用src参数时,将文件的内容直接设置为指定的值。远端创建有指定内容的文件,并且只能设置简单值。当设置复杂或格式化内容,用template模块。<br/>

force——默认为yes。当远程文件内容和源文件内容不同时,将覆盖目标文件。如果设置为no,文件将只被传输,在目标文件不存在时<br/>

remote-src——默认false。如果为true,那么将在远程/目标机器上搜索文件。2.8版本开始支持递归copy。<br/>

follow——yes/no。当拷贝的文件夹内有link存在的时候,那么拷贝过match去的也会有link

[study@c7study ~/.ssh]$ ansible www -u manager -m shell -a 'echo -e "abc\ndef" >/tmp/hosts'
156.96.148.72 | CHANGED | rc=0 >>
[study@c7study ~/.ssh]$ ansible www -u manager -m shell -a "cat /tmp/hosts"
156.96.148.72 | CHANGED | rc=0 >>
abc
def
[study@c7study ~/.ssh]$ ^C
[study@c7study ~/.ssh]$ ansible www -u manager -m copy -a "src=/etc/hosts dest=/tmp/hosts backup=yes"     #《=====这里,用了backup=yes
156.96.148.72 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "backup_file": "/tmp/hosts.19719.2020-09-15@16:11:52~", 
    "changed": true, 
    "checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa", 
    "dest": "/tmp/hosts", 
    "gid": 1001, 
    "group": "manager", 
    "md5sum": "54fb6627dbaa37721048e4549db3224d", 
    "mode": "0664", 
    "owner": "manager", 
    "size": 158, 
    "src": "/home/manager/.ansible/tmp/ansible-tmp-1600157497.67-3521-279608571329628/source", 
    "state": "file", 
    "uid": 1001
}
[study@c7study ~/.ssh]$ ansible www -u manager -m shell -a "cat /tmp/hosts"
156.96.148.72 | CHANGED | rc=0 >>
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
[study@c7study ~/.ssh]$ ansible www -u manager -m shell -a "ls /tmp"
156.96.148.72 | CHANGED | rc=0 >>
ansible_command_payload_4WI3Xn
ansible_command_payload_z5ykCG
hosts
hosts.19719.2020-09-15@16:11:52~                               #《===========这里,备份后的文件,附加了时间戳信息
percona-version-check
systemd-private-b551031a4dbc4015a42883a5cc5143e2-php-fpm.service-0AYW2P
[study@c7study ~/.ssh]$ ansible www -u manager -m shell -a "cat /tmp/hosts.19719.2020-09-15@16:11:52~"
156.96.148.72 | CHANGED | rc=0 >>
abc
def

<br/>

④script模块<br/>

作用:在远程主机上执行ansible主机上的脚本,且不需要将脚本复制到被执行的远程主机上。

参数:<br/>

脚本路径,必须参数

chdir:在执行脚本之前,先进入到指定目录

creates:当远程主机上的该文件存在时,不执行脚本;反之执行

removes:当远程主机上的该文件不存在时,不执行脚本;反之执行

⑤file模块

主要用于远程机器上的文件操作,file模块包含以下参数:

force:当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件。不过强制创建链接文件分为三种情况。情况一:当要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,会将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件。

group: 定义文件目录属性,用于指定被操作文件的属主,属主对应的用户必须在远程主机中存在,否则会报错。

mode:定义文件目录的权限,比如,如果想要将文件权限设置为”rw-r-x---“,则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的。如果想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700。

owner:定义文件目录的所有者,属主对应的用户必须在远程主机中存在,否则会报错。

path:必选项,定义文件目录的路径。在之前版本的ansible中,使用dest参数或者name参数指定要操作的文件或目录,为了兼容之前的版本,使用dest或name也可以

recurse: 只对目录有效,当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性。

src:只适用于state=link或hard的情况。当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源。

dest:被连接到的路径,,只适用于state=link或hard的情况<br/>

state:以下是stat的各种值

  • directory:如果目录不存在,创建目录<br/>

  • file:即使文件不存在,也不会被创建<br/>

  • link:创建软连接<br/>

  • hard:创建硬链接<br/>

  • touch:如果文件不存在时候,则则会创建一个新文件,如存在文件目录,则更新最后修改时间<br/>

  • absent:删除目录文件或者取消连接文件<br/>

⑥yum模块

参数比较多,常用的2个

name:需要安装的软件包名称,或包的版本标识信息

state:是否安装(present or installed, lastest),或者是删除(absent or removed)软件包<br/>⑦systemed模块

常用的参数:<br/>

name:指定服务名称,必须是全称,比如crond.service

state:可以是started,stopped,restarted,reloaded四个值

enable:可以是yes或no的值

scope:可选值为user、system、global。该参数用于定义执行systemctl的能力。默认的应该为root用户,对应的是system的能力。对于user来说,执行命令的用户必须拥有开启dbus示例的权限。常规理解,对于普通拥有sudo权限的用户,则应制定为global。global是面向所有用户的。

[study@m01 ~]$ansible test -m systemd -a "name=crond.service state=restarted scope=global"    #《=====“test”清单中的主机,均启用的是study的普通sudo用户开启ssh通道

tools from working.
172.16.1.81 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "name": "crond.service", 
    "state": "restarted", 
    "status": {}
}
172.16.1.71 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "name": "crond.service", 
    "state": "restarted", 
    "status": {}
}

<br/>

// 查看全文
2020 9月 09