使用正则表达式在 Vim 中的每个捕获组中用下划线替换空格
Replacing spaces with underscores within each capture group in Vim using regex
我经常在使用 Power BI 时使用 Vim 编辑 Power Query“M”代码。通常我更喜欢为每个更改自动生成的标识符名称
通过用下划线替换空格并将其转换为小写来查询步骤。带空格的标识符表示为带# 前缀的引号字符串
比如#"Change Column Types"
。对于该示例,我希望每个实例都转换为 change_column_types
。
我想创建一个可以在所有实例的任何缓冲区内执行此操作的键映射。
示例文件如下所示,后面是所需的 'cleaned' 文件:
输入:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"id", Int64.Type}, {"foo", type text}, {"bar", type text}, {"baz", Int64.Type}}),
#"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([foo] = "sdf")),
#"Grouped Rows" = Table.Group(#"Filtered Rows", {"bar"}, {{"Count", each Table.RowCount(_), Int64.Type}})
in
#"Grouped Rows"
期望的输出:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
changed_type = Table.TransformColumnTypes(Source,{{"id", Int64.Type}, {"foo", type text}, {"bar", type text}, {"baz", Int64.Type}}),
filtered_rows = Table.SelectRows(changed_type, each ([foo] = "sdf")),
grouped_rows = Table.Group(filtered_rows, {"bar"}, {{"Count", each Table.RowCount(_), Int64.Type}})
in
grouped_rows
诀窍在于,这涉及尝试替换每个捕获组中的多个(未知数量的)字符。
由于每个单词通常只有 2 或 3 个单词,我可以使用两个 ex 命令以一种 hacky 的方式处理这些单词:
:%s/\v\#"(\w+)\s(\w+)"/\L_\L/gc
:%s/\v\#"(\w+)\s(\w+)\s(\w+)"/\L_\L_\L/gc
但是,这显然并不理想,因为它被硬编码为仅支持特定数量的单词。
我试过做一些嵌套分组,但问题似乎还是一样。
有没有办法在其他一些替换操作中定义替换模式?
任何有关如何正确处理此问题的帮助将不胜感激。
下面为 <space>
-<c>
创建一个映射以将字符串转换为标识符:
noremap <space>c :%s/#"\([^"]\+\)"/\=substitute(tolower(submatch(1)), " ", "_", "g")/g<CR>
关于这里发生的事情的一点解释 - 替换的替换部分的 \=
部分表示我们将把这个表达式作为 vim 脚本来评估,而不是将其视为文字文本。我们使用 submatch(1)
获取第一个捕获组的文本,将其转换为小写,然后进行第二次替换(空格为下划线)。
请注意,有一些边缘情况可能会遇到问题 - 如果需要,我可以将正则表达式编辑得更复杂(并且可能更脆弱)以处理这些情况。
- 如果字符串可以以单引号而不是双引号开头,则不会匹配它们。我不知道这是否是 Power Query“M”会遇到的问题。
- 如果字符串包含转义字符(反斜杠),则不会处理。
- 如果字符串以数字开头,这可能无法成为目标语言/格式(如果它与大多数语言一样)的有效标识符。
我经常在使用 Power BI 时使用 Vim 编辑 Power Query“M”代码。通常我更喜欢为每个更改自动生成的标识符名称
通过用下划线替换空格并将其转换为小写来查询步骤。带空格的标识符表示为带# 前缀的引号字符串
比如#"Change Column Types"
。对于该示例,我希望每个实例都转换为 change_column_types
。
我想创建一个可以在所有实例的任何缓冲区内执行此操作的键映射。
示例文件如下所示,后面是所需的 'cleaned' 文件:
输入:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"id", Int64.Type}, {"foo", type text}, {"bar", type text}, {"baz", Int64.Type}}),
#"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([foo] = "sdf")),
#"Grouped Rows" = Table.Group(#"Filtered Rows", {"bar"}, {{"Count", each Table.RowCount(_), Int64.Type}})
in
#"Grouped Rows"
期望的输出:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
changed_type = Table.TransformColumnTypes(Source,{{"id", Int64.Type}, {"foo", type text}, {"bar", type text}, {"baz", Int64.Type}}),
filtered_rows = Table.SelectRows(changed_type, each ([foo] = "sdf")),
grouped_rows = Table.Group(filtered_rows, {"bar"}, {{"Count", each Table.RowCount(_), Int64.Type}})
in
grouped_rows
诀窍在于,这涉及尝试替换每个捕获组中的多个(未知数量的)字符。 由于每个单词通常只有 2 或 3 个单词,我可以使用两个 ex 命令以一种 hacky 的方式处理这些单词:
:%s/\v\#"(\w+)\s(\w+)"/\L_\L/gc
:%s/\v\#"(\w+)\s(\w+)\s(\w+)"/\L_\L_\L/gc
但是,这显然并不理想,因为它被硬编码为仅支持特定数量的单词。 我试过做一些嵌套分组,但问题似乎还是一样。 有没有办法在其他一些替换操作中定义替换模式? 任何有关如何正确处理此问题的帮助将不胜感激。
下面为 <space>
-<c>
创建一个映射以将字符串转换为标识符:
noremap <space>c :%s/#"\([^"]\+\)"/\=substitute(tolower(submatch(1)), " ", "_", "g")/g<CR>
关于这里发生的事情的一点解释 - 替换的替换部分的 \=
部分表示我们将把这个表达式作为 vim 脚本来评估,而不是将其视为文字文本。我们使用 submatch(1)
获取第一个捕获组的文本,将其转换为小写,然后进行第二次替换(空格为下划线)。
请注意,有一些边缘情况可能会遇到问题 - 如果需要,我可以将正则表达式编辑得更复杂(并且可能更脆弱)以处理这些情况。
- 如果字符串可以以单引号而不是双引号开头,则不会匹配它们。我不知道这是否是 Power Query“M”会遇到的问题。
- 如果字符串包含转义字符(反斜杠),则不会处理。
- 如果字符串以数字开头,这可能无法成为目标语言/格式(如果它与大多数语言一样)的有效标识符。