【问题标题】:Swap text around equal sign在等号周围交换文本
【发布时间】:2010-11-25 08:05:43
【问题描述】:

是否有一种简单的方法可以在 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 中的单行来实现。

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

【问题讨论】:

    标签: vim vi


    【解决方案1】:
    :%s/\([^ =]*\)\s*=\s*\([^;]*\);/\2 = \1;/
    

    【讨论】:

    • 请对此添加一些解释,以便其他人学习
    • 对超过 2 或 3 英寸的压缩正则表达式逐个字符级别的解释将需要数页才能向外行描述。描述它通常被认为在社会上是不可接受的,就像不受欢迎的医学上正确的精神分析或在杂货店称某人肥胖一样。
    【解决方案2】:

    类似这样的:

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

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

    编辑:解释

    我们使用s/find/replace 命令。 find 部分告诉我们:

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

    然后我们添加几个捕获括号来保存构造替换字符串所需的内容,即\(stuff\) 语法

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

    【讨论】:

    • 我明白了。我的意思是说,如果您的代码的其他部分更复杂,例如有多个 '=' 或 ';'在一行上(即使在引用的表达式中),如果不进一步调整,我的解决方案将无法工作。
    • 没关系。通常当我必须翻转类似的东西时,它们的行格式为“lvalue = rvalue;”上面,所以你的解决方案一针见血。
    • 这个需要个等号周围有空格吗?它不适用于“lvalue=rvalue;”我相信。 depesz 的解决方案没有这个问题。
    • 空格(技术上)是可选的,但我通常在左值、右值和运算符之间使用空格编写赋值语句。
    【解决方案3】:

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

    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
      • 删除多余的空间
    • 一个
      • 转到行尾并进入插入模式
    • &lt;BACKSPACE&gt; = &lt;ESC&gt;
      • 删除分号,插入等号和空格
    • "+p
      • 将之前复制的测试插入到寄存器“+”中
    • xi;&lt;ESC&gt;
      • 重新插入尾随分号
    • j
      • 向下移动到下一行,准备重新应用宏
    • q
      • 停止录制

    【讨论】:

    • 我不知道你可以在 vim 中录制这样的宏。
    • 我总觉得这是 vim 的杀手级功能之一;在宏之前,我经常会陷入其中一个重复循环,在 20 个连续的行上执行相同的无脑操作。
    • 我经常将这样的宏与 :g... 结合使用,例如 :g/something/normal @q
    • 您可以使用普通命令“:.,+20 normal @q”直接使用范围。我有时会选择一系列行(shift+V),然后执行 :normal
    【解决方案4】:
    :%s/^\s*\(.\{-}\)\s*=\s*\(.\{-}\)\s*;\s*$/\2 = \1;/
    

    应该很好用。

    【讨论】:

    • 这行得通,我试过了,但我不确定 \(.\{-}\) 部分是否有效。我知道那些匹配等号两边的代码片段。你能解释一下这些代码段是如何工作的吗?
    • ...不要贪心,不像'*'
    猜你喜欢
    • 1970-01-01
    • 2019-05-25
    • 2020-08-18
    • 2015-03-05
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多