在 vim 中重新格式化以获得良好的列布局

我在一个 csv 文件中有这个数据集

1.33570301776, 3.61194e-06, 7.24503e-06, -9.91572e-06, 1.25098e-05, 0.0102828, 0.010352, 0.0102677, 0.0103789, 0.00161604, 0.00167978, 0.00159998, 0.00182596, 0.0019804, 0.0133687, 0.010329, 0.00163437, 0.00191202, 0.0134425
1.34538754675, 3.3689e-06, 9.86066e-06, -9.12075e-06, 1.18058e-05, 0.00334344, 0.00342207, 0.00332897, 0.00345504, 0.00165532, 0.00170412, 0.00164234, 0.00441903, 0.00459294, 0.00449357, 0.00339737, 0.00166596, 0.00451926, 0.00455153
1.34808186291, -1.99011e-06, 6.53026e-06, -1.18909e-05, 9.52337e-06, 0.00158065, 0.00166529, 0.0015657, 0.0017022, 0.000740644, 0.00078635, 0.000730052, 0.00219736, 0.00238191, 0.00212762, 0.00163783, 0.000750669, 0.00230171, 0.00217917

正如您所看到的,这些数字的格式不同,而且排列不对。在 vim 中是否有一种方法可以快速正确地对齐列,从而得到如下结果

1.33570301776,  3.61194e-06, 7.24503e-06, -9.91572e-06, 1.25098e-05, 0.0102828,  0.010352,   0.0102677,  0.0103789, 0.00161604, 0.00167978, 0.00159998, 0.00182596, 0.0019804,  0.0133687,  0.010329,   0.00163437, 0.00191202, 0.0134425
1.34538754675,  3.3689e-06,  9.86066e-06, -9.12075e-06, 1.18058e-05, 0.00334344, 0.00342207, 0.00332897, 0.00345504,0.00165532, 0.00170412, 0.00164234, 0.00441903, 0.00459294, 0.00449357, 0.00339737, 0.00166596, 0.00451926, 0.00455153
1.34808186291, -1.99011e-06, 6.53026e-06, -1.18909e-05, 9.52337e-06, 0.00158065, 0.00166529, 0.0015657,  0.0017022, 0.000740644,0.00078635, 0.000730052,0.00219736, 0.00238191, 0.00212762, 0.00163783, 0.000750669,0.00230171, 0.00217917

这将是伟大的复制和粘贴与 ctrl-v 部分。有什么提示吗?

74904 次浏览

如果您使用的是某种 UNIX (Linux 等) ,您可以通过 column (1)命令进行欺骗和过滤。

:%!column -t

上面的代码将解析字符串文字中错误的分隔符,因此您可能需要预处理步骤,并为这个文件指定分隔符,例如:

%!sed 's/","/\&/' | column -t -s '&'

正如 sunny256建议的那样,column命令是在 Unix/Linux 机器上实现这一点的一个很好的方法,但是如果你想在纯 Vim 中实现(这样它也可以在 Windows 中使用) ,最简单的方法是安装 对齐插件,然后执行:

:%Align ,
:%s/\(\s\+\),\s/,\1/g

第一行对齐逗号上的条目,第二行移动逗号,使其与前面的值齐平。您可以使用 AlignCtrl来定义一个自定义映射,它可以一次性完成所有工作,但是我从来不记得如何使用它..。

剪辑

如果您不介意条目之间有两个空格,并且希望在一个命令中完成此操作,那么还可以这样做:

:%Align ,\zs

另外,如果您有很长的列,它可以方便地禁用默认包装

:set nowrap
:%!column -t

(注意,在 debian 中,如果想拆分多个相邻的分隔符,还有一个 column-n 选项)

你可以使用 CSV.vim插件。

:%ArrangeColumn

但是,这并不能完全满足您的要求: 它将正确地调整单元格的内容,而您的值将按小数点或第一个数字对齐。

该插件还有许多其他用于处理 CSV 文件的有用命令。

这是一个伟大的答案使用 vim 宏: https://stackoverflow.com/a/8363786/59384-基本上,你开始记录一个宏,格式化第一列,停止记录,然后重复所有剩余行的宏。

复制/粘贴这个答案:

qa0f:w100i <Esc>19|dwjq4@a

注意100i 之后的单个空格,< Esc > 表示“按转义键”——不要按字面意思输入“ < Esc >”。

翻译过来就是:

qa         -- record macro in hotkey a
0          -- go to beginning of line
f:         -- go to first : symbol
w          -- go to next non-space character after the symbol
100i <Esc> -- insert 100 spaces
19|        -- go to 19th column (value 19 figured out manually)
dw         -- delete spaces until : symbol
j          -- go to next line
q          -- stop recording macro
4@a        -- run the macro 4 times (for the remaining 4 lines)

我用 Perl 编写了一个 cli 工具。

你可以在这里找到它: https://github.com/bas080/colcise

有时候我们只想排列两列。在这种情况下,我们不需要任何插件,可以像下面这样使用纯 Vim 功能:

  1. 选择一个分隔符。在 OP 的文章中,这是一个逗号,在我的例子中,这是 =
  2. 在它之前/之后添加空格。我在视觉选择中使用了 s/=/= ...spaces... /
  3. 定位到最长的单词,并在其后放置光标。
  4. 使用 dw和垂直移动删除所有额外的空格。

这种技术的例子如下:

Example

我发现自己不需要经常对齐东西来安装另一个插件,所以这是我更喜欢的完成它的方式-特别是它不需要太多的思考。

这是个老问题了,但我最近使用了一个优秀的 vim 插件,它可以在运行时或事后(根据用例需要)进行表格格式化:

Https://github.com/dhruvasagar/vim-table-mode

我们现在还有神话般的 EasyAlign插件,由 junegunn 编写。

演示自述文件中的 GIF:

为此,我刚刚编写了 桌子

pip3 install tablign --user

然后简单地在 vim 中标记表并执行

:'<,'>:!tablign

enter image description here

这是一个纯 Vim 脚本的答案,没有插件,没有宏:

以我的问题的解决方案作为例子开始可能是最清楚的。我选择了我想要影响的代码行,然后使用以下命令(回想一下,从可视模式进入命令模式会自动前置“’< ,’>”,因此它在可视范围内起作用) :

:'<,'>g``normal / "value<0d>D70|P`

除了我没有真正地输入“ < 0d”。您可以通过按 ctrl-v,然后按您要键入的键,在命令行中输入不可打印的字符。“ < 0d >”是在输入“ ctrl-v enter”之后在命令行上呈现的内容。在这里,它被“ Normal”命令解析为从“/”搜索模式退出。然后,光标跳转到当前行中的“ value”。

然后我们简单地[ D ]删除行的其余部分,跳转到第70列(或者您所需要的任何内容) ,然后[ P ]删除我们刚刚删除的内容。这意味着我们必须确定最宽线的宽度,直到我们的搜索。如果您还没有将这些信息放到 statusline 中,那么您可以通过输入标准模式命令‘ g ctrl-g’来查看光标的列。还要注意的是,跳转到一个不存在的列需要设置为“ virtual aledit”!

我把: g (global)命令的搜索关键词留空,因为我们使用了一个可视化块,并希望影响每一行,但是您可以停止使用可视化选择(和“’< ,’>”) ,而在那里放一个搜索关键词。或者将视觉选择和搜索词结合起来,以更精细/更容易地缩小范围。

我最近学到了一些东西: 如果你搞砸了一个复杂的命令模式命令,用‘ u’撤消(如果它影响了缓冲区) ,然后按“ q:”键进入一个特殊的命令历史缓冲区,它的作用类似于传统的缓冲区。编辑任何一行并按回车键,已更改的命令将作为新命令输入。如果你不想在第一次就把所有事情都完美的表达出来,那么这就是不可或缺的。

我的 Vimrc 里有这个。

command! CSV set nowrap | %s/,/,|/g | %!column -n -t -s "|"

这样可以在保持逗号的同时对齐列,稍后可能需要使用逗号进行正确读取。例如,对于 PythonPandasread_csv(..., skipinitialspace=True),感谢熊猫们提供了这个聪明的选项,否则在 vim%s/,\s\+/,/g中。如果你的 column可以选择 输出分离器的话,可能会容易一些,我猜,我的没有,我也不确定为什么(我的专栏的手册页写着2004,在 ubuntu 18.04上,不确定 ubuntu 会不会有一个新版本)。无论如何,这对我很有用,如果你有任何建议,请评论。