sed:如何在正则表达式中插入换行符?

sed:如何在正则表达式中插入换行符?

我正在尝试格式化文本文件。现在它通常看起来像这样:

ApartCD 光盘CD-ROM 光盘只读存储器CD-RW 可重写光盘CDFS 光盘文件系统CERT 计算机紧急响应小组CFS 中央文件系统、通用文件系统或命令文件系统ACRONYM SPELLED OUTCGA 计算机图形和应用CIDR 无类域间路由CIFS通用互联网文件系统CMOS 互补金属氧化物半导体CNR 通信和网络 RiserCOMx 通信端口(x=端口号)CPU 中央处理单元CRT 阴极射线管DaaS 数据即服务DAC 自主访问控制DB-25 串行通信 D-Shell 连接器,25 针DB-9 串行通信 D-Shell 连接器,9 针DBaaS 数据库即服务 DC 直流电 DDoS 分布式拒绝服务DDR 双倍数据速率DDR RAM 双倍数据速率随机存取存储器DFS 分布式文件系统DHCP 动态主机配置协议DIMM 双列直插内存模块DIN 德国工业规范DLT 数字线性磁带DLP 数字光P

这只是我复制的一个示例。首先,我想在每个小写字母后面紧跟一个大写字母的实例之间插入换行符。我通过阅读 GNU sed 手册发现我可以使用括号范围[:lower:][:upper:]为此(我认为[[:lower:]]+[[:upper:]]这是正确的模式),但我还没有确定正确的命令或通用语法来完成这项工作。我发现了几个用于附加换行符的命令,但没有一个用于将它们插入正则表达式。

这是我第一次使用 sed。我不知道这是否是最适合这项工作的工具。非常感谢您的任何帮助,如果不是太麻烦,请解释您的命令,这样我也许可以学到一些东西,而不必在将来打扰任何人。谢谢。

答案1

使用 GNU sed 试试这个:

$ sed 's/\([a-z]\+\)\([A-Z]\)/\1\n\2/g' text.txt 

对于您的输入,它会产生:

s Apart
CD Compact Disc
CD-ROM Compact Disc-Read-Only Memory
CD-RW Compact Disc-Rewritable
CDFS Compact Disc File System
CERT Computer Emergency Response Team
CFS Central File System, Common File System, or Command File System
ACRONYM SPELLED OUTCGA Computer Graphics and Applications
CIDR Classless Inter-Domain Routing
CIFS Common Internet File System
CMOS Complementary Metal-Oxide Semiconductor
CNR Communications and Networking Riser
COMx Communication port (x=port number)CPU Central Processing Unit
CRT Cathode-Ray Tube
Daa
S Data as a Service
DAC Discretionary Access Control
DB-25 Serial Communications D-Shell Connector, 25 pins
DB-9 Serial Communications D-Shell Connector, 9 pins
DBaa
S Database as a Service DC Direct Current
DDo
S Distributed Denial of Service
DDR Double Data Rate
DDR RAM Double Data Rate Random Access Memory
DFS Distributed File System
DHCP Dynamic Host Configuration Protocol
DIMM Dual Inline Memory Module
DIN Deutsche Industrie Norm
DLT Digital Linear Tape
DLP Digital Light P

一些解释:

我假设您知道“捕获组”是什么,因为您了解该模式。

该字符串's/\([a-z]\+\)\([A-Z]\)/\1\n\2/g'按字符分为 4 部分/

第一部分的s意思是代替

第二部分是模式。该模式包含两个捕获组:[a-z]\+[A-Z]。以您输入的“DDoS”一词为例。第一个捕获组将捕获“o”,第二个捕获组将捕获“S”。整个模式匹配“oS”。

第三部分\1\n\2将替换与模式匹配的字符串。\1指第一个捕获组[a-z]\+,在“DDoS”示例中,它是“o”。\2指的是第二个捕获组[A-Z],在“DDoS”示例中,它是“S”。\n表示换行符。因此,将它们组合在一起,您将得到“o\nS”,它将替换匹配的字符串“oS”。

第四部分的g意思是全球的。如果省略,sed将找到第一个匹配项,进行替换并退出。使用g,sed将搜索所有匹配的字符串并进行替换。

您可以参考sed手册详细说明。

答案2

GNUsed能够使用其s///命令插入换行符:

sed -e 's/\([[:lower:]]\)\([[:upper:]]\)/\1\n\2/g' file

非 GNU sed(如 macOS、BSD 和其他非 Linux 系统)不知道命令\n的替换文本中的含义s///,只会插入一个n字符。

要替换换行符,您必须转义字面换行符,如

sed -e 's/\([[:lower:]]\)\([[:upper:]]\)/\1\
\2/g' file

或使用解决方法,例如插入数据中尚不存在的其他占位符字符,然后使用y///换行符替换它们(y///命令理解\n):

sed -e 's/\([[:lower:]]\)\([[:upper:]]\)/\1@\2/g' -e 'y/@/\n/' file

或者

sed -e 's/\([[:lower:]]\)\([[:upper:]]\)/\1@\2/g' file | tr '@' '\n'

请注意,[[:lower:]]匹配单个字符,而[[:lower:]]+(或[[:lower:]]\{1,\}当写为基本正则表达式时)匹配至少一个字符。在这种情况下,我们不需要+(或\{1,\}),因为它足以匹配单个小写字符。

相关内容