我希望使用 vim 从包含以下示例文本的文件中仅提取方括号和里面的数字:
13_[4]_3_[4]_[1]_5_[1]_29_[3]_4_[2]_9_[1]_6_[2]_4
14_[4]_28_[3]_4_[2]_12_[1]_8_[2]_2
[1]_[4]_15_[1]_16_[3]_4_[2]_11_[1]_16_[2]_2
9_[4]_3_[4]_3_[4]_9_[4]_4_[4]_7_[1]_12_[3]_4_[2]_9_[1]_[2]_2
14_[4]_30_[3]_4_[2]_5_[1]_19_[1]_3_[1]_8_[2]_10_[1]_4_[1]_3_[1]_2
因此,对于第一个示例行,我想要一个如下所示的输出行:
[4][4][1][1][3][2][1][2]。
我可以轻松删除方括号:
:%s/\[\d\]//g
但是我在尝试删除所有与 [/d] 不匹配的文本时遇到了麻烦。大多数使用否定的 vim 命令(例如:v)似乎只对整行而不是单个字符串进行操作,并且使用 %s 进行组匹配:
:%s/\v(.*)([\d])(.*)/\2
也匹配和删除方括号。
有人会建议解决我的问题吗?
最佳答案
你很接近。您需要引用方括号并使用比 .*
少得多的东西.
:%s/\v[^[]*(\[\d\])[^[]*/\1/g
概述
匹配前导文本 +
[
+ 数字 + ]
+ 尾随文本。捕获 [
+ 数字 + ]
.替换匹配的捕获组。只留下括号和数字。细节的荣耀
\v
非常神奇。见 :h magic
[...]
是一个括号中的字符类,它匹配里面的任何字符。例如fooba[rs]
匹配 foobar
和 foobas
,但不是 foobaz
.见 :h /\[
. (注意 Vim 可能将其称为集合。)[^...]
是一个否定的括号字符类,因此不匹配括号内的任何字符。例如fooba[^rz]
匹配 foobas
,但不是 foobaz
和 foobar
. [^[]
- 匹配任何非 [
特点。 (这看起来很有趣)[^[]*
- 匹配是非 [
字符零次或多次。这将匹配我们要删除的前导文本。 (...)
- 捕获组\[
& \]
表示文字 [
/]
.我们必须转义以防止字符类。 \d
匹配 1 个数字。 [^[]*
- 匹配要删除的尾随文本 \1
替换将是我们的捕获组又名括号数字。 g
标记以全局或更简单地多次执行此操作。 %
做一个替换,:s
, 在整个文件中, 1,$
. 那么为什么
:%s/\v(.*)([\d])(.*)/\2
失败?tl;dr:您的模式不匹配。试试
/[\d]
.长版:
.*
将捕获太多只留下最后一部分。例如[2]...
. [\d]
创建与以下字符之一匹配的括号字符类:d
或 \
.*
使用 g
时遇到与第一个相同的问题旗帜。 g
旗帜。这意味着该命令每行只会进行 1 次替换,这将留下大量文本。 一般正则表达式和替换建议
在处理棘手的正则表达式模式时,通常最好从搜索开始,
/
, 而不是替代品。这使您可以事先查看匹配项的位置。您可以通过 /
调整您的搜索并按下 <up>
或 <c-p>
.甚至更好地使用 q/
打开command-line-window
所以你可以像编辑任何文本一样编辑你的模式。您也可以使用 <c-f>
在命令行(包括 /
)上调出 command-line-window
.一旦你有了你的模式,那么你就想开始你的替换。 Vim 通过使用空模式提供了使用当前搜索的快捷方式。例如
:%s//\1/g
.这种技术特别与
set incsearch
结合使用和 set hlsearch
, 意味着您可以在进行替换之前以交互方式查看您的匹配项。此技术显示在以下 Vimcast 中插曲:Refining search patterns with the command-line window .需要学习更多正则表达式语法吗?见
:h pattern
.这是一篇很长很密集的读物,但对你将来会有很大帮助。我还发现通过 perldoc perlre
阅读 Perl 的正则表达式文档也是一个好看的地方。注意:Perl 的正则表达式与 Vim 的正则表达式不同(参见 :h perl-patterns
),但 Perl 兼容正则表达式 (PCRE) 非常常见。想法
您也可以考虑
grep -o
.例如%!grep -o '\[\d\]'
.更多帮助
:h :s
:h range
:h magic
:h /\[
:h /\(
:h s/\1
:h /\d
:h :s_flags
:h 'hlsearch'
:h 'incsearch'
:h q/
:h command-line-window
:h :range!
关于regex - 使用 vim 替换出现次数可变的不匹配字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31544848/