考虑到特殊的正则表达式,如何正确使用 sed 替换命令的反向引用

How to use back-reference of sed replacement command correctly considering a special Regular Expression

我正在学习 linux 上的 sed s/regexp/replacement/ 命令。

有一些数字来自 phone.txt

(555)555-1212
(555)555-1213
(555)555-1214
(666)555-1215
(777)555-1217

我想使用正则表达式(我在 https://www.freeformatter.com/regex-tester.html 上测试过)

 (\(555\))(.*-)(.*$)

匹配以 (555) 开头的数字。然后我希望这些匹配数字的这三个部分的输出为:(数字 (555)555-1212 的示例)

Area code: (555) Second: 555- Third: 1212

我尝试了以下命令:

cat phone.txt | sed 's/\(\\(555\\)\)\(.*-\)\(.*$)/Area code:  Second:  Third: /'

但是系统给了我:

sed: -e expression #1, char 66: Unmatched ( or \(

所有数字的通用命令是:

cat phone.txt | sed 's/\(.*)\)\(.*-\)\(.*$\)/Area code:  Second:  Third: /'

来源:https://www.tutorialspoint.com/unix/unix-regular-expressions.htm

但我只想对 以 (555) 开头的数字执行 sed,并通过 反向引用 将其添加到输出中。

你能告诉我如何正确编写这个特殊命令吗?

Ypu 在您的 sed 命令中使用 POSIX BRE 语法,在这种模式中,未转义的括号与文字括号匹配。此处转义的括号定义捕获组。

您可以使用

sed -E 's/(\(555\))(.*-)(.*)/Area code:  Second:  Third: /'

online demo

POSIX ERE 语法中的文字括号(通过 -E 选项启用)被转义,就像在所有常见的在线正则表达式测试器中一样,未转义的括号定义捕获组。

您可以使用字符串中包含的格式进行概括,以挑选出第一个 555、第二个 555 和第三个 1212,而无需将自己限制在字符串中的任何特定前缀s/find/replace/ sed 的替换形式。然后,您可以根据需要通过在替换之前包含匹配条件来进行限制,您可以在其中输入 555666,等等...

要将模式匹配与替换一起包括在内,请使用以下形式:

sed '/pattern/s/find/replace/'

要使模式匹配抑制除与模式匹配的行之外的所有行的输出,您传递 -n 选项以抑制模式 space 的打印,并在以下位置包含 p替代形式的末尾以显式打印那些匹配的行,例如

sed -n '/pattern/s/find/replace/p'

现在,让我们来谈谈您手头的问题。要将重新格式化的输出限制为仅以 (555) 开头的行,您可以这样做:

$ sed -n '/^(555)/s/^(\([^)]*\))\([^-]*\)-\(.*\)$/Area code: () Second: - Third: /p' file
Area code: (555) Second: 555- Third: 1212
Area code: (555) Second: 555- Third: 1213
Area code: (555) Second: 555- Third: 1214

(注意: 反向引用只捕获数字而不是 (..)'-')

要重新格式化所有行,您可以删除 -n/pattern/ 以及最后的 p,仅使用基础 sed 's/find/replace/ 形式,例如

$ sed 's/^(\([^)]*\))\([^-]*\)-\(.*\)$/Area code: () Second: - Third: /' file
Area code: (555) Second: 555- Third: 1212
Area code: (555) Second: 555- Third: 1213
Area code: (555) Second: 555- Third: 1214
Area code: (666) Second: 555- Third: 1215
Area code: (777) Second: 555- Third: 1217

检查一下,如果您还有其他问题,请告诉我。