49、正则表达式与高级sed编辑器使用指南

正则表达式与高级sed编辑器使用指南

正则表达式的应用

正则表达式在数据处理和验证方面发挥着重要作用。在Linux环境中,它被广泛应用于各种工具和编程语言中。

电话号码验证

可以使用脚本来验证电话号码的有效性。例如,通过 gawk 命令结合正则表达式来过滤电话号码。以下是具体的操作步骤:
1. 创建一个脚本 isphone ,脚本中的 gawk 命令在shell脚本中为单行。
2. 可以通过重定向将电话号码传递给脚本进行处理,示例如下:

$ echo "317-555-1234" | ./isphone
317-555-1234
$ echo "000-555-1234" | ./isphone
$ echo "312 555-1234" | ./isphone
312 555-1234
  1. 也可以将包含电话号码的整个文件重定向到脚本,以过滤出无效的号码:
$ cat phonelist
000-000-0000
123-456-7890
212-555-1234
(317)555-1234
(202) 555-9876
33523
1234567890
234.123.4567
$ cat phonelist | ./isphone
212-555-1234
(317)555-1234
(202) 555-9876
234.123.4567

只有与正则表达式模式匹配的有效电话号码才会显示出来。

电子邮件地址解析

如今,电子邮件已成为一种重要的通信方式。验证电子邮件地址对于脚本编写者来说是一项挑战,因为创建电子邮件地址的方式多种多样。电子邮件地址的基本形式为: username@hostname
- 用户名规则 :用户名可以使用任何字母数字字符,以及以下特殊字符:
- 点( .
- 连字符( -
- 加号( +
- 下划线( _
这些字符可以以任何组合形式出现在有效的电子邮件用户ID中。
- 主机名规则 :电子邮件地址的主机名部分由一个或多个域名和一个服务器名组成。服务器名和域名必须遵循严格的命名规则,只允许使用字母数字字符,以及以下特殊字符:
- 点( .
- 下划线( _
服务器名和域名由点分隔,服务器名在前,任何子域名在后,顶级域名不带尾随点。

构建用于验证电子邮件地址的正则表达式模式的步骤如下:
1. 从左侧开始构建用户名部分的模式: ^([a-zA-Z0-9_\-\.\+]+)@ ,此分组指定了用户名中允许的字符,加号表示至少必须有一个字符。
2. 主机名部分的模式: ([a-zA-Z0-9_\-\.]+) ,该模式可以匹配 server server.domain server.subdomain.domain 等文本。
3. 顶级域名部分的模式: \.([a-zA-Z]{2,5})$ ,顶级域名只能是字母字符,长度不少于2个字符(用于国家代码)且不超过5个字符。
4. 将整个模式组合起来: ^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$

创建脚本 isemail 来实现该正则表达式,示例如下:

$ echo "rich@here.now" | ./isemail
rich@here.now
$ echo "rich@here.now." | ./isemail
$
$ echo "rich@here.n" | ./isemail
$
$ echo "rich@here-now" | ./isemail
$
$ echo "rich.blum@here.now" | ./isemail
rich.blum@here.now
$ echo "rich_blum@here.now" | ./isemail
rich_blum@here.now
$ echo "rich/blum@here.now" | ./isemail
$
$ echo "rich#blum@here.now" | ./isemail
$
$ echo "rich*blum@here.now" | ./isemail
$

这个例子展示了正则表达式的强大功能和简洁性。乍一看,过滤电子邮件地址的正则表达式似乎很复杂,但逐步分析模式会使理解变得更容易。

正则表达式总结

在shell脚本中处理数据文件时,需要熟悉正则表达式。正则表达式通过正则表达式引擎在Linux实用工具、编程语言和应用程序中实现。在Linux环境中,有多种不同的正则表达式引擎可供使用,其中最流行的两种是POSIX基本正则表达式(BRE)引擎和POSIX扩展正则表达式(ERE)引擎。 sed 主要遵循BRE引擎,而 gawk 则利用了ERE引擎中的大多数特性。

正则表达式定义了一个模式模板,用于过滤数据流中的文本。该模式由标准文本字符和特殊字符组合而成。特殊字符由正则表达式引擎用于匹配一个或多个字符序列,类似于其他应用程序中的通配符字符的工作方式。

通过组合字符和特殊字符,可以定义一个模式来匹配几乎任何类型的数据。然后可以使用 sed gawk 从较大的数据流中过滤特定数据,或验证从数据输入应用程序接收到的数据。

高级sed编辑器

基本的 sed 编辑器命令能够满足大多数日常文本编辑需求,但 sed 编辑器还提供了一些更高级的功能,这些功能可能不常用,但在需要时非常有用。

多行命令

使用基本的 sed 编辑器命令时,会发现一个限制:所有 sed 编辑器命令都在单行数据上执行。 sed 编辑器在读取数据流时,会根据换行符将数据分成多行,然后逐行处理数据,执行定义的脚本命令,再处理下一行。

有时需要对跨越多行的数据执行操作,特别是在查找或替换短语时。例如,在数据中查找短语“Linux System Administrators Group”时,该短语的单词可能会被分割到两行。如果使用普通的 sed 编辑器命令处理文本,将无法检测到分割的短语。

sed 编辑器提供了三个特殊命令来处理多行文本:
- N命令 :将数据流中的下一行添加到当前行,创建一个多行组进行处理。
- D命令 :删除多行组中的第一行。
- P命令 :打印多行模式空间中的第一行。

以下是对这些多行命令的详细介绍:

单线下一命令(n)

单线下一命令( n )告诉 sed 编辑器移动到数据流中的下一行文本,而不返回命令的开头。通常, sed 编辑器会在一行上执行所有定义的命令,然后再移动到下一行。 n 命令改变了这种处理流程。

例如,有一个包含五行数据的文件,其中两行是空白行。目标是删除标题行后的第一行空白行,同时保留第二行空白行。如果编写一个 sed 脚本来删除空白行,会删除所有空白行,这不是我们想要的结果:

$ cat data1.txt
Header Line

Data Line #1

End of Data Lines
$
$ sed '/^$/d' data1.txt
Header Line
Data Line #1
End of Data Lines

由于要删除的行是空白的,没有可以搜索的文本以唯一标识该行。解决方案是使用单线下一命令( n )。脚本查找包含单词“Header”的唯一行,找到后, n 命令将 sed 编辑器移动到下一行,即空白行:

$ sed '/Header/{n ; d}' data1.txt
Header Line
Data Line #1

End of Data Lines

此时, sed 编辑器继续处理命令列表,使用 d 命令删除空行。当 sed 编辑器到达命令脚本的末尾时,它从数据流中读取下一行文本,并从命令脚本的顶部开始处理命令。由于没有找到包含单词“Header”的另一行,因此不会再删除其他行。

多行下一命令(N)

单线下一命令( n )将数据流中的下一行文本移动到 sed 编辑器的处理空间(称为模式空间)。多行下一命令( N )将下一行文本添加到模式空间中已有的文本中。

这会将数据流中的两行文本组合到同一个模式空间中,两行文本仍由换行符分隔,但 sed 编辑器现在可以将这两行文本视为一行。

以下是多行( N )命令的操作示例:

$ cat data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
$ sed '/First/{ N ; s/\n/ / }' data2.txt
Header Line
First Data Line Second Data Line
End of Data Lines

sed 编辑器脚本查找包含单词“First”的文本行,找到后,使用 N 命令将下一行与该行组合到模式空间中,然后使用替换( s )命令将换行符( \n )替换为空格。结果是文本文件中的两行在 sed 编辑器输出中显示为一行。

这在搜索可能在数据文件中被分割到两行的文本短语时很有用。例如:

$ cat data3.txt
On Tuesday, the Linux System
(Continues)
Admin group meeting will be held.
All System Admins should attend.
Thank you for your cooperation.
$
$ sed 's/System Admin/DevOps Engineer/' data3.txt
On Tuesday, the Linux System
Admin group meeting will be held.
All DevOps Engineers should attend.
Thank you for your cooperation.

替换( s )命令在文本文件中查找特定的双词短语“System Admin”。在短语出现在单行的情况下,替换命令可以正常替换文本。但在短语被分割到两行的情况下,替换命令无法识别匹配的模式。

N 命令可以帮助解决这个问题:

$ sed 'N ; s/System.Admin/DevOps Engineer/' data3.txt
On Tuesday, the Linux DevOps Engineer group meeting will be held.
All DevOps Engineers should attend.
Thank you for your cooperation.

通过使用多行( N )命令将下一行与找到第一个单词的行组合起来,可以检测到短语中的行分割情况。

需要注意的是,替换( s )命令在单词“System”和“Admin”之间使用了通配符模式( . )来匹配空格和换行符情况。但当匹配到换行符时,它会从字符串中删除该换行符,导致两行合并为一行,这可能不是我们想要的结果。

为了解决这个问题,可以在 sed 编辑器脚本中使用两个替换命令,一个用于匹配多行情况,另一个用于匹配单行情况:

$ sed 'N
> s/System\nAdmin/DevOps\nEngineer/
> s/System Admin/DevOps Engineer/
> ' data3.txt
On Tuesday, the Linux DevOps
Engineer group meeting will be held.
All DevOps Engineers should attend.
Thank you for your cooperation.

第一个替换命令专门查找两个搜索词之间的换行符,并将其包含在替换字符串中,这样可以在新文本中相同的位置添加换行符。

然而,这个脚本还有一个小问题:脚本在执行 sed 编辑器命令之前总是将下一行文本读入模式空间。当到达最后一行文本时,没有下一行文本可供读取,因此 N 命令会导致 sed 编辑器停止。如果匹配的文本在数据流的最后一行,命令将无法捕获匹配的数据:

$ cat data4.txt
On Tuesday, the Linux System
Admin group meeting will be held.
All System Admins should attend.
$
$ sed 'N
> s/System\nAdmin/DevOps\nEngineer/
> s/System Admin/DevOps Engineer/
> ' data4.txt
On Tuesday, the Linux DevOps
Engineer group meeting will be held.
All System Admins should attend.

由于“System Admin”文本出现在数据流的最后一行,多行( N )命令会错过它,因为没有另一行可以读入模式空间进行组合。可以通过将单行编辑命令移到多行命令之前,只将多行编辑命令放在 N 命令之后来解决这个问题:

$ sed '
> s/System Admin/DevOps Engineer/
> N
> s/System\nAdmin/DevOps\nEngineer/
> ' data4.txt
On Tuesday, the Linux DevOps
Engineer group meeting will be held.
All DevOps Engineers should attend.

现在,查找单行短语的替换( s )命令在数据流的最后一行也能正常工作,而多行( N )命令之后的替换命令则处理数据流中间出现的情况。

多行删除命令(D)

在之前的介绍中提到了单线下一命令( d ), sed 编辑器使用它来删除模式空间中的当前行。但在使用 N 命令时,使用单线下一命令要小心:

$ sed 'N ; /System\nAdmin/d' data4.txt
All System Admins should attend.

删除( d )命令查找分别在两行中的单词“System”和“Admin”,并删除模式空间中的两行。这可能不是我们想要的结果。

sed 编辑器提供了多行删除( D )命令,它只删除模式空间中的第一行,即删除直到并包括换行符的所有字符:

$ sed 'N ; /System\nAdmin/D' data4.txt
Admin group meeting will be held.
All System Admins should attend.

N 命令添加到模式空间的第二行文本保持不变。这在需要删除出现在找到数据字符串的行之前的一行文本时非常有用。

例如,删除数据流中第一行之前出现的空白行:

$ cat data5.txt

Header Line
First Data Line

End of Data Lines
$
$ sed '/^$/{N ; /Header/D}' data5.txt
Header Line
First Data Line

End of Data Lines

这个 sed 编辑器脚本查找空白行,然后使用 N 命令将下一行文本添加到模式空间中。如果新的模式空间内容包含单词“Header”, D 命令将删除模式空间中的第一行。如果没有 N D 命令的组合,将无法在不删除所有其他空白行的情况下删除第一行空白行。

多行打印命令(P)

多行打印命令( P )遵循与其他多行命令相同的模式,它只打印多行模式空间中的第一行,包括模式空间中直到换行符的所有字符。当使用 -n 选项抑制脚本的输出时,它的使用方式与单线下一命令( p )类似,用于显示文本。

$ sed -n 'N ; /System\nAdmin/P' data3.txt
On Tuesday, the Linux System

当发生多行匹配时, P 命令只打印模式空间中的第一行。将多行 P 命令与 N D 多行命令结合使用时,其强大之处就会显现出来。

D 命令有一个独特的功能:在从模式空间中删除第一行后,它会强制 sed 编辑器返回到脚本的开头,并在当前模式空间上重复执行命令(不从数据流中读取新的一行文本)。通过在命令脚本中包含 N 命令,可以有效地逐行遍历模式空间,将多行匹配在一起。

然后,使用 P 命令打印第一行,再使用 D 命令删除第一行并返回到脚本的开头。当回到脚本开头时, N 命令读取下一行文本,重新开始整个过程。这个循环会一直持续到到达数据流的末尾,如下例所示,用于修复文件中的数据损坏问题:

$ cat corruptData.txt
Header Line#
@
Data Line #1
Data Line #2#
@
End of Data Lines#
@
$
$ sed -n '
> N
> s/#\n@//
> P
> D
> ' corruptData.txt
Header Line
Data Line #1
Data Line #2
End of Data Lines

数据文件在某些行的末尾出现了 # ,后面跟着下一行的 @ ,导致数据损坏。为了解决这个问题,使用 sed 将“Header Line#”行加载到模式空间中,然后多行下一命令( N )将第二行( @ )加载到模式空间中,并将其追加到第一行。替换( s )命令通过将有问题的数据( #\n@ )替换为空来删除它。然后, P 命令只打印模式空间中现在已清理的第一行。删除( D )命令从模式空间中删除第一行,并返回到脚本的开头,此时下一个 N 命令将第三行(“Data Line #1”)文本读入模式空间,编辑循环继续进行。

综上所述,正则表达式和高级 sed 编辑器功能为数据处理和文本编辑提供了强大的工具。通过合理运用这些技术,可以更高效地处理各种数据和文本任务。

以下是一个总结正则表达式和高级 sed 命令的表格:
| 技术 | 功能 | 相关命令 |
| ---- | ---- | ---- |
| 正则表达式 | 过滤数据流中的文本,验证数据 | - |
| 高级sed | 处理多行文本,包括组合、删除和打印多行 | N、D、P |

下面是一个mermaid格式的流程图,展示了使用 N P D 命令处理多行文本的过程:

graph TD;
    A[开始] --> B[读取一行到模式空间];
    B --> C{是否匹配条件};
    C -- 是 --> D[N命令添加下一行];
    C -- 否 --> B;
    D --> E[执行替换等操作];
    E --> F[P命令打印第一行];
    F --> G[D命令删除第一行];
    G --> B;

通过这些技术和工具,我们可以更好地应对各种数据处理和文本编辑的挑战。

正则表达式与高级sed编辑器使用指南(续)

高级sed编辑器的其他高级特性

除了前面介绍的多行命令, sed 编辑器还有一些其他的高级特性,这些特性在特定的场景下能发挥重要作用。

否定命令

sed 中,可以对某些命令进行否定操作,即不执行该命令。这在需要排除某些特定情况时非常有用。例如,要删除除了包含特定单词的行之外的所有行,可以使用否定命令。

假设我们有一个文件 data6.txt ,内容如下:

Line 1
Special Line
Line 2

如果我们想删除不包含“Special”的行,可以使用如下命令:

$ sed '/Special/!d' data6.txt
Special Line

这里的 ! 符号表示否定, /Special/!d 表示对不包含“Special”的行执行删除操作。

改变命令流

sed 允许改变命令的执行流程,例如使用分支和跳转。其中一个常用的命令是 b (分支)命令,它可以根据条件跳转到指定的标签处继续执行命令。

以下是一个简单的示例,假设我们有一个文件 data7.txt ,内容如下:

Start
Middle
End

我们可以使用 b 命令来实现条件跳转:

$ sed '/Middle/{b end}; p; :end' data7.txt
Start
End

在这个例子中,当 sed 遇到包含“Middle”的行时,会跳转到标签 end 处,跳过 p 命令(打印当前行),因此“Middle”这一行不会被打印出来。

通过模式进行替换

除了基本的替换命令 /s sed 还支持通过模式进行替换。例如,我们可以使用模式匹配来替换特定格式的文本。

假设我们有一个文件 data8.txt ,内容如下:

Date: 2023-01-01
Date: 2024-02-02

如果我们想将日期格式从 YYYY-MM-DD 替换为 MM/DD/YYYY ,可以使用如下命令:

$ sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\2\/\3\/\1/' data8.txt
Date: 01/01/2023
Date: 02/02/2024

这里使用了正则表达式的分组功能, \([0-9]\{4\}\) 匹配四位数字的年份, \([0-9]\{2\}\) 分别匹配两位数字的月份和日期,然后在替换部分使用 \2\/\3\/\1 将它们重新组合成新的日期格式。

在脚本中使用sed

sed 命令集成到脚本中可以实现自动化的文本处理任务。以下是一个简单的脚本示例,用于将文件中的所有“old”替换为“new”:

#!/bin/bash
# 脚本名为 replace.sh
if [ $# -ne 1 ]; then
    echo "Usage: $0 <filename>"
    exit 1
fi
filename=$1
sed -i 's/old/new/g' $filename
echo "Replacement completed in $filename"

在这个脚本中,首先检查是否提供了文件名作为参数,如果没有则输出使用说明并退出。然后使用 sed -i 命令直接在文件中进行替换操作, -i 表示直接修改文件内容, s/old/new/g 表示将所有的“old”替换为“new”。

使用这个脚本的步骤如下:
1. 保存脚本为 replace.sh
2. 给脚本添加执行权限: chmod +x replace.sh
3. 运行脚本: ./replace.sh your_file.txt

创建sed实用工具

可以将常用的 sed 操作封装成实用工具,方便重复使用。例如,创建一个用于删除文件中所有空白行的实用工具。

#!/bin/bash
# 脚本名为 remove_blank_lines.sh
if [ $# -ne 1 ]; then
    echo "Usage: $0 <filename>"
    exit 1
fi
filename=$1
sed -i '/^$/d' $filename
echo "Blank lines removed from $filename"

这个脚本的使用步骤与上面的 replace.sh 类似,它会直接删除指定文件中的所有空白行。

总结与展望

正则表达式和高级 sed 编辑器为我们提供了强大的数据处理和文本编辑能力。正则表达式可以帮助我们过滤和验证各种数据,而高级 sed 编辑器的特性,如多行命令、否定命令、改变命令流等,让我们能够处理更复杂的文本编辑任务。

在实际应用中,我们可以根据具体的需求灵活运用这些技术。例如,在处理日志文件时,可以使用正则表达式过滤出特定的日志信息,再使用 sed 进行进一步的处理;在批量处理文本文件时,将 sed 命令集成到脚本中可以提高处理效率。

以下是一个总结高级 sed 命令及其功能的表格:
| 命令 | 功能 |
| ---- | ---- |
| /pattern/!command | 对不匹配 pattern 的行执行 command |
| b label | 跳转到指定的 label 处继续执行命令 |
| s/pattern/replacement/g | 通过模式匹配进行全局替换 |

下面的mermaid流程图展示了使用 sed 脚本处理文件的一般流程:

graph TD;
    A[开始] --> B{是否提供文件名};
    B -- 是 --> C[读取文件];
    B -- 否 --> D[输出使用说明并退出];
    C --> E[执行sed命令];
    E --> F{是否修改成功};
    F -- 是 --> G[输出处理完成信息];
    F -- 否 --> H[输出错误信息];
    G --> I[结束];
    H --> I;

通过不断学习和实践,我们可以更好地掌握这些技术,从而更高效地完成各种数据处理和文本编辑工作。

基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归神经网络模型线性化”展开,旨在研究纳米定位系统的预测控制方法。通过结合数据驱动技术Koopman算子理论,将非线性系统动态近似为高维线性系统,进而利用递归神经网络(RNN)建模并实现系统行为的精确预测。文中详细阐述了模型构建流程、线性化策略及在预测控制中的集成应用,并提供了完整的Matlab代码实现,便于科研人员复现实验、优化算法并拓展至其他精密控制系统。该方法有效提升了纳米级定位系统的控制精度动态响应性能。; 适合人群:具备自动控制、机器学习或信号处理背景,熟悉Matlab编程,从事精密仪器控制、智能制造或先进控制算法研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①实现非线性动态系统的数据驱动线性化建模;②提升纳米定位平台的轨迹跟踪预测控制性能;③为高精度控制系统提供可复现的Koopman-RNN融合解决方案; 阅读建议:建议结合Matlab代码逐段理解算法实现细节,重点关注Koopman观测矩阵构造、RNN训练流程模型预测控制器(MPC)的集成方式,鼓励在实际硬件平台上验证并调整参数以适应具体应用场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值