12

有没有一种简单的方法可以在 vi/vim 中围绕等号翻转代码?

例如:我想转这个:

value._1 = return_val.delta_clear_flags;
value._2._1 = return_val.delta_inactive_time_ts.tv_sec;
value._2._2 = return_val.delta_inactive_time_ts.tv_nsec;
value._3    = return_val.delta_inactive_distance_km;
(...)

进入这个:

return_val.delta_clear_flags = value._1;
return_val.delta_inactive_time_ts.tv_sec = value._2._1;
return_val.delta_inactive_time_ts.tv_nsec = value._2._2;
return_val.delta_inactive_distance_km = value._3;
(...)

在文件中的很多行上。

我知道这似乎有点微不足道,但是在过去我需要这样做的编码时,我遇到了很多情况,而且我从来没有一个好的想法/方法来做到这一点需要大量输入 vim 或编写 awk 脚本。我认为这可以通过 vi 中的单行来实现。

单行的解释非常受欢迎,当我选择我接受的答案时会受到高度重视。:)

4

4 回答 4

29

像这样的东西:

:%s/\([^=]*\)\s\+=\s\+\([^;]*\)/\2 = \1

如果您的代码比示例中显示的更复杂,您可能需要稍微摆弄一下。

编辑:解释

我们使用s/find /replace命令。查找部分为我们提供了以下信息:

  1. 由除等号之外的任何符号组成的最长可能字符串,由[^=]*...表示
  2. ... 后跟一个或多个空格, (前面\s\+的多余是 vim 怪异)\+
  3. ...接着是=任意数量的空格,=\s\+
  4. ... 后跟可能的最长非分号字符串,[^;]*

然后我们加入几个捕获括号来保存我们需要构建替换字符串的东西,这就是\(stuff\)语法

最后,我们在find replace命令的替换部分使用捕获的字符串:即和。s//\1\2

于 2009-09-03T15:30:45.763 回答
11

出于兴趣,以下是我将其作为录制宏的方式:

qq0"+df=xA<BACKSPACE> = <ESC>"+pxi;<ESC>jq

在第一行执行该设置将“q”宏设置为执行所需的操作。然后在随后的每一行中,您可以通过键入以下命令来执行宏:

@q

或者,假设您想将宏应用到接下来的 10 行:

10@q

我总是发现像这样的快速切换宏比找出正则表达式更容易,因为它们本质上是我手动操作的扩展。

编辑:Dan Olson 在他的评论中指出,如果您想将宏应用于一系列行,例如第 6-100 行,您可以输入以下内容。我不知道是否有更简洁的语法不需要“。*”模式匹配。

:6,100g/.*/normal @q

宏的解释

  • QQ
    • 开始在寄存器 q 中记录
  • 0
    • 转到行首
  • "+df=
    • 删除直到'='并将文本放入'+'寄存器
  • X
    • 删除多余的空间
  • 一个
    • 转到行尾并进入插入模式
  • <BACKSPACE>=<ESC>
    • 删除分号,插入等号和空格
  • "+p
    • 将之前复制的测试插入寄存器“+”
  • 十一;<ESC>
    • 重新插入尾随分号
  • j
    • 向下移动到下一行,准备重新应用宏
  • q
    • 停止录制
于 2009-09-03T16:12:38.893 回答
4
:%s/^\s*\(.\{-}\)\s*=\s*\(.\{-}\)\s*;\s*$/\2 = \1;/

应该工作得很好。

于 2009-09-03T15:49:36.747 回答
0
:%s/\([^ =]*\)\s*=\s*\([^;]*\);/\2 = \1;/
于 2019-01-26T10:11:44.633 回答