我在文件中包含这些字符串:
a b
a-b
a / b / c
我想用以下内容替换它们:
"a b" => a_b
"a-b" => a_b
"a / b / c" => a_b_c
如何编写正则表达式?还请解释正则表达式并命名所涉及的概念。
答案 0 :(得分:2)
这不仅仅是替换中的简单捕获和重新排序。将非字母字符修改为_
需要包含匹配的替换。这可以通过:help sub-replace-expr
:
:%substitute/.*/\='"' . submatch(0) . '" => ' . substitute(submatch(0), '\A\+', '_', 'g')/
基本上,这匹配整行,然后替换为双引号中的匹配,后跟=>
,然后匹配非字母字符序列(\A\+
)替换为单_
1}}。
您也可以分两步执行此操作:首先复制并引用该行:
:%substitute/.*/"&" => &/
然后,需要修改第二个副本。要将替换应用于仅在=>
分隔符后匹配,必须提供肯定的后视(必须在=>
+任何字符之后匹配):
:%substitute/\%(=> .*\)\@<=\A\+/_/g
答案 1 :(得分:2)
另一种方式:
:g/^/co.|-s/.*/"&" =>/|+s/\W\+/_/g|-j
概述:
对于每一行:g/^/
,复制一行(:copy
),然后替换为在第一行添加"..." =>
并对其上的非字母字符进行替换下一行_
。然后加入两行-j
。
细节的荣耀:
:g/{pat}/{cmd}
- 在与{cmd}
匹配的每一行上运行{pat}
。使用^
匹配每一行copy .
- 复制当前行(.
)下方的当前行。简短:co.
-1s/.*/.../
- :s
上面一行(-1
)。替换整行,.*
"&" =>
- &
是整个匹配(或PRCE中的\0
)+s/\W\+/_/g
- 在:s
+1
)上执行全局_
-j
- 从上面一行开始:join
使用下一行获取更多帮助:
:h :g
:h :copy
:h :s
:h :j
:h :range
答案 2 :(得分:1)
这样做的一种方法:
:%s/[\ -]\/*\ */_/g
[\ -]
会查找空格\
(请注意\
和-
之间的空格)或短划线-
。
星号*
表示0或N次出现。所以\/*
0或N次出现斜线/
; \ *
0或N次出现的空格。最后g
替换该行中的所有匹配项。
<强> [编辑] 强>
我误解了这个问题。您的问题可以通过两个步骤使用多个子表达式来解决。
步骤1)在c
之前加上下划线:%s/c/_c/g
步骤2)找到并替换
:%s/a\([\ -]\/*\ *\)b\(\1\)*\(_\)*\(c\)*/"a\1b\2\4" => a_b\3\4/g
这会给你
"a b" => a_b
"a-b" => a_b
"a / b / c" => a_b_c
说明:
\(\)
表示一个子表达式,外观顺序很重要,因此\ 1与子表达式1匹配等等。
诀窍是在某个地方添加_
,以便我们可以使用它,同时获取有关长度的信息。因为它只出现在c之前,所以子表达式\3
只匹配该行的_
。
现在,通过"a\1b\2\4"
替换,我们跳过\3
,避免添加下划线。
答案 3 :(得分:1)
这实现了你所要求的,虽然这个问题有些含糊不清:
%s/\(\a\)\A\+/\1_/g
%s / [find_pattern] / [replace_pattern / g确实查找并替换文件中的每一行(%),并执行任意数量的匹配(g),而不是第一个匹配的默认行为。
(\ a)捕获组(括号必须转义),包含字母字符。
\ A +表示一个或多个非字母字符
/ 1是模式中第一个捕获的组的反向引用。在这种情况下,括号中的字母字符。
_只是文字。
所以它一起取代每个字母,后跟一个或多个非字母,后跟_。所以这仅在行以最后一个字母结束时才有效。
答案 4 :(得分:1)
:%s:[\ /-]\+:_:g
说明:
s: : : - Substitute command (with delimiter `:`)
[\ /-] - Match a ` ` (space), `/`, or `-` character
\+ - Match one or more of the previous group consecutively
_ - Replace with one `_` character
g - Replace all matches in line
% - Execute command on every line in file (optional)
我将您的问题解释为非常通用。如果您需要匹配更具体的模式,请准确说明需要匹配的内容。
如果您需要完全匹配' / '
,请使用:
:%s:\ /\ \|[\ -]:_:g
s: : : - Substitute command (with delimiter `:`)
\| - Match left pattern OR right pattern
\ /\ - Match ` / ` exactly
[\ -] - Match a ` ` (space) or `-` character
_ - Replace with one `_` character
g - Replace all matches in line
% - Execute command on every line in file (optional)
我误解了你想要替代的东西。
如果你正试图用a做这件事,那么你的生活将会非常困难
单一的正则表达式。它会变得如此复杂,此时你会变得更好
写一个小函数,就像其他一些答案一样。但你应该这样
能够逃脱两个替换命令,而不会太疯狂。
一个用于前两个字符串(a b
和a-b
),另一个用于第三个字符串
(a / b / c
)。
%s:\v(\a+)[\ -](\a+):"\0"\ =>\ \1_\2
%s:\v(\a+)\s*/\s*(\a+)\s*/\s*(\a+):"\0"\ =>\ \1_\2_\3
说明:
%s:\v(\a+)[\ -](\a+):"\0"\ =>\ \1_\2
s: : - Substitute command (with delimiter `:`)
\v - Very Magic mode *
( ) ( ) - Capture contained matches into numbered sub-expressions
\a+ \a+ - Match at least one alphanumeric character
[\ -] - Match either ` ` (space) or `-`
" "\ =>\ _ - Literal text
\0 - Replace with entire matched text
\1 \2 - Replace with first and second `()` sub-expression, respectively
% - Execute command on every line in file (optional)
%s:\v(\a+)\s*/\s*(\a+)\s*/\s*(\a+):"\0"\ =>\ \1_\2_\3
s: : - Substitute command (with delimiter `:`)
\v - Very Magic mode *
( ) ( ) ( ) - Capture contained matches into numbered sub-expressions
\a+ \a+ \a+ - Match at least one alphanumeric character
\s*/\s* \s*/\s* - Match a `/` and any surrounding spaces
" "\ =>\ _ _ - Literal text
\0 - Replace with entire matched text
\1 \2 \3 - Replace with first, second, and third `()` sub-expression, respectively
% - Execute command on every line in file (optional)
* This eliminates the need for a lot of ugly backslashes.
See `:h /magic` and `:h /\v`