Vim 替换一行子串中的几个相似元素
Vim replace several similar elements in a substring of a line
我需要格式化很多 JSON 条目。目标是用已经存在的文本的 Title Cased 版本替换值部分,并使用空格而不是下划线。这些条目看起来类似于:
"ASDF": "TUOJKLDSF",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH_SDF",
我试图让它们看起来像这样:
"ASDF": "Tuojkldsf",
"ASDF": "Tuojkldsf Fugzihojkowg",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh Sdf",
我遇到的问题是我需要保持第一部分不变,所以我不能只替换所有的 A-Z 实例,而且我无法找到一种在一个命令中完成所有操作的好方法。
我最后做的是为值中的每个“单词”数量编写一个单独的命令:
:%s/\([^:\n]\+: "\)\([A-Z]\)\([A-Z]\+\)"/\L"
"ASDF": "Tuojkldsf",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH_SDF",
:%s/\([^:\n]\+: "\)\([A-Z]\)\([A-Z]\+\)_\([A-Z]\)\([A-Z]\+\)"/\L\E \L"
"ASDF": "Tuojkldsf",
"ASDF": "Tuojkldsf Fugzihojkowg",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH_SDF",
这工作正常,但我想用一个命令完成这个?
一种方法是先将下划线更改为 spaces 然后 运行 a
所有行的正常模式命令:
:%s/_/ /g | %norm f:gu[=10=]Wl~W.W.W.W.W.
:%s/_/ /g
将每一行的每个下划线替换为 space。
|
应用另一个命令。
:%norm
对每一行应用以下正常模式命令。
f:
将光标移动到冒号。
gu$
小写该行的其余部分。
0Wl
将光标移动到值的开头(就在引用部分内)。
~
首字母小写。
W.
移动到下一个单词(在 whitespace 之后)并重复小写命令。
只要你输入足够多W.
它就会给你你想要的输出(因为
对于 :%norm
,W
动作不会移动到下一行)。
结果:
"ASDF": "Tuojkldsf",
"ASDF": "Tuojkldsf Fugzihojkowg",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh Sdf",
Vim 可以处理正则表达式中的大小写。 \U
匹配大写,\L
匹配小写。您也可以在替换时使用这些来更改大小写。
要使用 |
“另一个命令”管道在一行中执行此操作,我会这样处理:
:%s/_/ /g |
Whole file, substitute "_" with " ", all occurences; + more command
%s/\(\a\)\(\a*\)/\L/g |
%s/ / /g | Whole file, substitute, all occurences; + more
\(\a\) Backref capture 1 (first letter of a word)
\(\a*\) Backref capture 2 (remaining letters of word)
\L Backref 1; lowercase the next; backref 2
This would leave us with Asdf at the front, but we want ASDF so:
%s/^\("\a\{4\}": \)/\U/
%s/ / / Whole file, subst. (no "g"; should be 1 per line)
^ Start of line
\("\a\{4\}": \) Backref is quote, 4 letters, quote, colon, space
\U Uppercase the next; backref 1
全部放在一条线上:
:%s/_/ /g|%s/\(\a\)\(\a*\)/\L/g|%s/^\("\a\{4\}": \)/\U/
其他方法也是可能的——不是将第一个字母作为单独的反向引用捕获组,而是将整行小写,然后将大写应用于每个单词的第一个字母;等等
我需要格式化很多 JSON 条目。目标是用已经存在的文本的 Title Cased 版本替换值部分,并使用空格而不是下划线。这些条目看起来类似于:
"ASDF": "TUOJKLDSF",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH_SDF",
我试图让它们看起来像这样:
"ASDF": "Tuojkldsf",
"ASDF": "Tuojkldsf Fugzihojkowg",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh Sdf",
我遇到的问题是我需要保持第一部分不变,所以我不能只替换所有的 A-Z 实例,而且我无法找到一种在一个命令中完成所有操作的好方法。
我最后做的是为值中的每个“单词”数量编写一个单独的命令:
:%s/\([^:\n]\+: "\)\([A-Z]\)\([A-Z]\+\)"/\L"
"ASDF": "Tuojkldsf",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH_SDF",
:%s/\([^:\n]\+: "\)\([A-Z]\)\([A-Z]\+\)_\([A-Z]\)\([A-Z]\+\)"/\L\E \L"
"ASDF": "Tuojkldsf",
"ASDF": "Tuojkldsf Fugzihojkowg",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH",
"ASDF": "TUOJKLDSF_FUGZIHOJKOWG_IKEH_SDF",
这工作正常,但我想用一个命令完成这个?
一种方法是先将下划线更改为 spaces 然后 运行 a 所有行的正常模式命令:
:%s/_/ /g | %norm f:gu[=10=]Wl~W.W.W.W.W.
:%s/_/ /g
将每一行的每个下划线替换为 space。|
应用另一个命令。:%norm
对每一行应用以下正常模式命令。f:
将光标移动到冒号。gu$
小写该行的其余部分。0Wl
将光标移动到值的开头(就在引用部分内)。~
首字母小写。W.
移动到下一个单词(在 whitespace 之后)并重复小写命令。
只要你输入足够多W.
它就会给你你想要的输出(因为
对于 :%norm
,W
动作不会移动到下一行)。
结果:
"ASDF": "Tuojkldsf",
"ASDF": "Tuojkldsf Fugzihojkowg",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh",
"ASDF": "Tuojkldsf Fugzihojkowg Ikeh Sdf",
Vim 可以处理正则表达式中的大小写。 \U
匹配大写,\L
匹配小写。您也可以在替换时使用这些来更改大小写。
要使用 |
“另一个命令”管道在一行中执行此操作,我会这样处理:
:%s/_/ /g |
Whole file, substitute "_" with " ", all occurences; + more command
%s/\(\a\)\(\a*\)/\L/g |
%s/ / /g | Whole file, substitute, all occurences; + more
\(\a\) Backref capture 1 (first letter of a word)
\(\a*\) Backref capture 2 (remaining letters of word)
\L Backref 1; lowercase the next; backref 2
This would leave us with Asdf at the front, but we want ASDF so:
%s/^\("\a\{4\}": \)/\U/
%s/ / / Whole file, subst. (no "g"; should be 1 per line)
^ Start of line
\("\a\{4\}": \) Backref is quote, 4 letters, quote, colon, space
\U Uppercase the next; backref 1
全部放在一条线上:
:%s/_/ /g|%s/\(\a\)\(\a*\)/\L/g|%s/^\("\a\{4\}": \)/\U/
其他方法也是可能的——不是将第一个字母作为单独的反向引用捕获组,而是将整行小写,然后将大写应用于每个单词的第一个字母;等等