Ant*_*yBB 5 sed text-processing regular-expression
我正在研究如何在不使用 Bash 中的递归的情况下生成一组数字的所有非重复排列,我发现这个答案有效,但我想了解原因。
假设您有三个数字:1、2、3。
以下命令将生成所有可能的非重复排列:
printf "%s\n" {1,2,3}{1,2,3}{1,2,3} | sort -u | sed '/\(.\).*\1/d'
123
132
213
231
312
321
Run Code Online (Sandbox Code Playgroud)
我理解当参数是集合 {1, 2, 3} 的大括号扩展三倍时printfwith 的%s作用(这将打印每个可能的结果)。
我知道这sort -u只会输出唯一的行。
我知道这sed /<pattern>/d用于删除任何匹配的行<pattern>。
读了里面的模式sed,我有些糊涂了。我知道如何阅读,regex但我没有看到这种模式在sed命令中是如何工作的。
\( = literal '('
. = any character, once
\) = literal ')'
.* = any character, zero or more times
\1 = reference to first captured group
Run Code Online (Sandbox Code Playgroud)
那么该sed命令如何从此regex模式中删除非唯一值?我不明白如何引用一个被捕获的组,而实际上没有一个?在模式中使用括号进行字面匹配?在sed命令之前,关于这次执行的一切对我来说都是有意义的。
作为第一步,您需要\(.\)正确理解。在基本的正则表达式中,它是一个捕获组,捕获任何字符,必须由\1. 这些不是文字括号。
现在,对于非常酷的部分!在每种情况下,正则表达式的每个元素匹配什么?
Left \(.\) .* \1 Right Result
111 1 1 1 Deleted!
112 1 1 2 Deleted!
113 1 1 3 Deleted!
121 1 2 1 Deleted!
122 1 2 2 Deleted!
123 ? ? ? NoMatch
131 1 3 1 Deleted!
132 ? ? ? NoMatch
133 1 3 3 Deleted!
Run Code Online (Sandbox Code Playgroud)
在 上122,如果不清楚:由于表达式未锚定,1向左移动,中间2匹配捕获组\(.\),最后2匹配反向引用\1。.*(匹配正则表达式的零个或多个字符)将尽最大努力适应字符串,因此在这种情况下它会收缩为空字符串。
如果您怀疑它,请尝试
echo 122 | grep --color=always '\(.\).*\1'
Run Code Online (Sandbox Code Playgroud)
您将看到只有22已着色的 。
将其与正则表达式的锚定版本进行比较:
$ printf "%s\n" {1,2,3}{1,2,3}{1,2,3} | sort -u | sed '/^\(.\).*\1$/d'
112
113
122
123
132
133
...
Run Code Online (Sandbox Code Playgroud)
现在没有“左”和“右”插槽:
^\(.\) .* \1$ Result
111 1 1 1 Deleted!
112 ? ? ? NoMatch
113 ? ? ? NoMatch
121 1 2 1 Deleted!
122 ? ? ? NoMatch
123 ? ? ? NoMatch
131 1 3 1 Deleted!
132 ? ? ? NoMatch
133 ? ? ? NoMatch
Run Code Online (Sandbox Code Playgroud)
第一个数字必须是这个版本的最后一个数字,所以匹配的少。