对齐vim第n列后的文本,删除不必要的空白

对齐vim第n列后的文本,删除不必要的空白,vim,Vim,在vim中,在Windows机器中(无法访问类似于“unix”的命令,如命令列),我希望重新格式化此代码以使其更具可读性: COLUMN KEY_ID FORMAT 9999999999 COLUMN VALUE_1 FORMAT 99 COLUMN VALUE_2 FORMAT 99 COLUMN VALUE_3 FORMAT 999 COLUMN V

在vim中,在Windows机器中(无法访问类似于“unix”的命令,如命令列),我希望重新格式化此代码以使其更具可读性:

COLUMN KEY_ID       FORMAT 9999999999
COLUMN VALUE_1                           FORMAT 99
COLUMN VALUE_2                            FORMAT 99
COLUMN VALUE_3              FORMAT 999
COLUMN VALUE_4        FORMAT 999
我希望使用尽可能少的命令:

COLUMN KEY_ID      FORMAT 9999999999
COLUMN VALUE_1     FORMAT 99
COLUMN VALUE_2     FORMAT 99
COLUMN VALUE_3     FORMAT 999
COLUMN VALUE_4     FORMAT 999

请注意,这只是一个摘录,因为还有许多行我必须这样做。

您可以使用以下命令:

:%s/\w\zs\s*\zeFORMAT/^I
该模式将匹配
格式
和上一个单词结尾之间的空格,并将其替换为一个制表符:

\w      Any 'word' character
\zs     Start the matching
\s*     Any number of whitespace
\ze     End the matching
FORMAT  The actual word format
\zs
\ze
仅允许在空白处应用替换请参见:和

请注意,
^I
应使用ctrl+vtab插入

@SatoKatsura推荐的方法也是一种很好的方法


你也可以概括一下。假设您有以下文件:

COLUMN KEY_ID           FORMAT 9999999999
COLUMN VALUE_1                      FOO 99
COLUMN VALUE_2      BAR 99
您可以使用以下命令:

:%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/  
图案是否可以这样详细描述:

^                 Match the beginning of the line
\(\w*\s\)\{1}     One occurrence of the pattern \w*\s i.e. one column
\w*               Another column
\zs\s*\ze         The whitespaces after the previous column
您可以更改
\{1}
的值,以便在下一列上应用该命令


编辑要回答@aturegano注释,以下是一种将列与另一列对齐的方法:

%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/\=repeat(' ', 30-matchstrpos(getline('.'), submatch(0))[1])
我们的想法仍然是匹配必须对齐的空白,在替换命令的第二部分中,我们使用了一个子替换表达式(请参阅)

这允许我们使用替换部分的命令,可以这样解释:

\=                 Interpret the next characters as a command
repeat(' ', XX)    Replace the match with XX whitespaces

XX is decomposed like this:
30-                 30 less the next expression
matchstrpos()[1]    Returns the columns where the second argument appears in the first one
getline('.')        The current line (i.e. the one containing the match
submatch(0)         The matched string
[1]                 Necessary since matchstrpos() returns a list:
                       [matchedString, StartPosition, EndPosition]
                    and we are looking for the second value.
然后,只需将30替换为要移动下一列的列


请参见和

您可以使用以下命令:

:%s/\w\zs\s*\zeFORMAT/^I
该模式将匹配
格式
和上一个单词结尾之间的空格,并将其替换为一个制表符:

\w      Any 'word' character
\zs     Start the matching
\s*     Any number of whitespace
\ze     End the matching
FORMAT  The actual word format
\zs
\ze
仅允许在空白处应用替换请参见:和

请注意,
^I
应使用ctrl+vtab插入

@SatoKatsura推荐的方法也是一种很好的方法


你也可以概括一下。假设您有以下文件:

COLUMN KEY_ID           FORMAT 9999999999
COLUMN VALUE_1                      FOO 99
COLUMN VALUE_2      BAR 99
您可以使用以下命令:

:%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/  
图案是否可以这样详细描述:

^                 Match the beginning of the line
\(\w*\s\)\{1}     One occurrence of the pattern \w*\s i.e. one column
\w*               Another column
\zs\s*\ze         The whitespaces after the previous column
您可以更改
\{1}
的值,以便在下一列上应用该命令


编辑要回答@aturegano注释,以下是一种将列与另一列对齐的方法:

%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/\=repeat(' ', 30-matchstrpos(getline('.'), submatch(0))[1])
我们的想法仍然是匹配必须对齐的空白,在替换命令的第二部分中,我们使用了一个子替换表达式(请参阅)

这允许我们使用替换部分的命令,可以这样解释:

\=                 Interpret the next characters as a command
repeat(' ', XX)    Replace the match with XX whitespaces

XX is decomposed like this:
30-                 30 less the next expression
matchstrpos()[1]    Returns the columns where the second argument appears in the first one
getline('.')        The current line (i.e. the one containing the match
submatch(0)         The matched string
[1]                 Necessary since matchstrpos() returns a list:
                       [matchedString, StartPosition, EndPosition]
                    and we are looking for the second value.
然后,只需将30替换为要移动下一列的列


请参阅和

有关对齐方式,有三个著名的插件:

  • 可敬的
  • 现代的
  • 竞争者

对于对齐,有三种著名的插件:

  • 可敬的
  • 现代的
  • 竞争者

根据要求发布答案:

:g/^COLUMN / s/.*/\=call('printf', ['%s %-30s %s %s'] + split(submatch(0)))/
说明:

  • g/^COLUMN/
    -将以下命令应用于与
    /^COLUMN/
    匹配的行(参见
    :h:global
  • \=
    -替换为表达式求值的结果,而不是固定字符串(参见
    :hs/\=
  • 子匹配(0)
    -匹配的行
  • 拆分(…)
    -将行拆分为单词
  • printf(…)
    -设置行的格式
  • call(…)
    -我们希望使用
    printf('%s%-30s%s%s',list)
    ,但是
    printf()
    不使用“真实”列表作为参数,因此我们必须使用
    调用(…)
    (参见
    :h call()
    )来展开列表

根据要求发布答案:

:g/^COLUMN / s/.*/\=call('printf', ['%s %-30s %s %s'] + split(submatch(0)))/
说明:

  • g/^COLUMN/
    -将以下命令应用于与
    /^COLUMN/
    匹配的行(参见
    :h:global
  • \=
    -替换为表达式求值的结果,而不是固定字符串(参见
    :hs/\=
  • 子匹配(0)
    -匹配的行
  • 拆分(…)
    -将行拆分为单词
  • printf(…)
    -设置行的格式
  • call(…)
    -我们希望使用
    printf('%s%-30s%s%s',list)
    ,但是
    printf()
    不使用“真实”列表作为参数,因此我们必须使用
    调用(…)
    (参见
    :h call()
    )来展开列表
另一种解决方案:

:%s/ \{2,}/   /g
此解决方案并不完美,因为结果在第一行上会有额外的单个空间。要解决此问题,请执行以下操作:

:%s/\%>15c \{2,}/   /g
图案说明:

%>15c\s\{2,}

%>15c                 Matches only after column 15

     \s\{2,}          Matches two or more white spaces
另一个解决方案:

:%s/ \{2,}/   /g
此解决方案并不完美,因为结果在第一行上会有额外的单个空间。要解决此问题,请执行以下操作:

:%s/\%>15c \{2,}/   /g
图案说明:

%>15c\s\{2,}

%>15c                 Matches only after column 15

     \s\{2,}          Matches two or more white spaces

安装插件并运行
:制表
。安装插件并运行
:制表
。非常好的方法和详细的解释。上面我没有提到我不想在代码中添加任何选项卡。表达式
:%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/
与我想要修改的内容相匹配,是否有任何方法可以指定“用空格填充n列”?@aturegano我认为对于这种用例,表格插件将是最简单的方法。也许你可以通过sub replace表达式()来破解一些东西:你可以用
/\=something
替换第二部分
/^I
,其中
something
将是对列的一个测试,将数字添加到空格中,但我不确定这是否可行。@aturegano我找到了一个解决方案,查看我的编辑并告诉我您是否需要:-)或者:
:g/^COLUMN/s/*/\=call('printf',['%s%-30s%s']]+split(submatch(0))/
@statox编辑后,答案完全解决。谢谢你的详细解释。请不要删除