我要转换
rat
ox
tiger
⋮
dog
pig
pig
dog
⋮
tiger
ox
rat
无需借助诸如
tac
之类的外部命令。#1 楼
全局的力量将在这里起作用::g/^/exe "normal ddggP"
或者,更简单地说(感谢@tommcdo)
:g/^/move 0
第一行将匹配每一行,并针对每一行将其删除并将其粘贴到文件顶部。当它在文件中移动时,它会反转文本。
第二个类似地匹配每一行并将其移动到文件的顶部。
注意:这两个工作在整个文件上,将不适用于反转行的子集。请参阅Ingo Karkat的答案以获取在一定范围内工作的解决方案。
描述:
g
全局命令/^/
匹配任何以开头(即所有行)开头的行exe
执行以下字符串"normal
执行普通模式命令dd
删除行gg
移至文件顶部P
粘贴在当前位置上方move 0
将当前行移至行0以下(将其置于位置1或第一行)的文件)评论
代替:normal命令,我们可以使用Ex命令:move 0,它将行移动到缓冲区的开头。
–tommcdo
15年2月22日在20:21
另外:execute仅在需要动态构建命令时才需要,例如:执行'普通'g:user_command。
–tommcdo
15年2月22日在20:23
@tommcdo好点!我有使用:execute的习惯,因为我经常会在以后的现有命令之后附加其他Ex命令,并且对我而言,拥有:exe比以后再回去插入它更方便。不幸的是,这个习惯渗入了这个答案中,但并没有那么广泛。
– John O'M。
15年2月22日在20:34
有关我使用:execute的更多说明:由于它使用字符串,因此可以清楚地描述普通模式命令的结束位置,即使我没有构造字符串,也比起查找引号要容易得多。寻找
– John O'M。
15年2月22日在20:41
这将在btw范围内起作用::9,11g / ^ / move 8 ...最后一个数字必须是范围的开始减去1(根据Ingo的答案改编)。
–马丁·图尔诺伊(Martin Tournoij)
2015年2月22日在21:05
#2 楼
这个单行代码(对于您的~/.vimrc
)定义了:Reverse
命令;您也可以直接使用:global
部分,但是:move
的语法(将行反复迭代到范围的开始之前,从而将其反转)并不容易记住::command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1
评论
作为读者的仅供参考,
–马丁·图尔诺伊(Martin Tournoij)
2015年2月22日在21:02
#3 楼
纯Vim::g/^/m0
解释:
根据
:help multi-repeat
,:g
及其表亲:v
以两遍方式工作。:g
的第一遍标记与{pattern}
匹配的每一行,而第二遍(显然是从文件的开头开始并执行到末尾)执行[cmd]
。上面对:g
的使用利用了行的处理顺序(虽然可以,尽管可能没有技术上的保证,但顺序还可以)。它的工作原理是首先标记每行,然后移动第一条标记的行到文件的顶部,然后将第二个移到文件的顶部(在先前移动的行上方),然后将第三个标记的行(同样在先前移动的行上方),依此类推,直到文件的最后一行
请注意,如果
:g
以从上到下的任何顺序处理行,则此命令将不起作用。来源:在vim Wikia上反转g的所有行和幂。
使用外部命令的几个示例:
tac
(GNU的一部分) coreutils-cat
反向)::%!tac
BSD / OSX上的
tail
(不兼容POSIX)::%!tail -r
-r
-r optio n使输入按行反向显示。检查:
man tar
了解更多详细信息。有关更多信息,请参阅:
如何反转文件中的行顺序?在stackoverflow SE
如何反转文本文件的行?在stackoverflow SE
如何从文件向后打印行(不使用“ tac”)?在Unix SE上
评论
:g / ^ / m0是否与:g / ^ / move 0相同,这是约翰的答案?
–muru
2015年2月23日下午13:15
@muru我认为是这样,但是这一段更短(根据vim wikia),并且我添加了一些不同的解释,并提供了一些其他使用命令行的示例。
– Kenorb
2015年2月23日在13:17
是的,由于其他命令,我投票赞成(我也来发布了tac)。但是我怀疑投票否定是因为重复了答案。
–muru
2015年2月23日下午13:18
我知道OP曾提到过tac,但是所有其他类似的问题无论如何都会重复出现,因此再次提及它是很好的。 John从@tommcdo评论中获取了此cmd,我最初是从DerMike那里获取的,但是我认为他只是从wikia中获取的,因此我对vim wikia表示感谢,因此,由于解释是完全不同的,因此并不完全相同。
– Kenorb
2015年2月23日在13:23
它增加了更多的价值,因为它的版本要短得多,而且要有适当的说明,我也相信正确的消息来源。使用shell命令非常简单方便。如果人们不同意,他们可以简单地投票,没什么大不了的。
– Kenorb
2015年2月23日在16:03
#4 楼
本着VimL功能的精神::call setline(1, reverse(getline(1, line('$'))))
getline(1, line('$'))
返回缓冲区中所有行的列表。 '$'
是line()
的特殊参数,它指示缓冲区中的最后一行。reverse(...)
就地反转输入列表。如果不应修改输入列表,则需要使用reverse(copy(...))
。setline(1, ...)
用第二个参数替换了指定的行。当第二个参数是列表时,将与列表长度相同的行数替换为列表的内容。如果您愿意,还可以定义一个包含范围的命令(默认为整个缓冲区
%
):command! -bar -range=% Reverse call setline(<line1>, reverse(getline(<line1>, <line2>)))
评论
我喜欢这个答案。它也不会像其他回答中的:g /命令那样突出显示某些内容(如果启用了hlsearch)...但是性能可能会更差?由于它是getline(1,line('$'))获取内存中的整个缓冲区。 reverse()似乎就位,因此应该只占用很少的内存...
–马丁·图尔诺伊(Martin Tournoij)
15年2月23日在15:35
#5 楼
根据Vim文档usr_12.txt-巧妙的技巧12.4反向行顺序
:global
命令可以与:move
命令结合使用来移动第一行之前的所有行,导致文件反转。
命令是:
:global/^/m 0
缩写:
:g/^/m 0
^
正则表达式与行的开头(即使该行为空白)。 :move
命令将匹配的行移动到神话中的第零行之后,因此当前的匹配行成为文件的第一行。由于更改行号不会混淆:global
命令,因此
:global
会继续匹配文件的所有剩余行,并将每行都放在第一行。这也适用于一系列线。首先移至第一行
上方,并用
mt
进行标记。然后将光标移到范围的最后一行并键入::'t+1,.g/^/m 't
#6 楼
使用相对数字。段落从第13行开始,垃圾邮件多了4行 :13,13+4g/^/m12
评论
对这个问题有更好标签的建议吗?也许是新的“ pure-vi”或类似标签?我已经看到几个可以从标记中受益的问题,这些标记表明不希望使用任何外部工具。我应该在Meta上问这个问题吗?
@Carpetsmoker(以及其他对此感兴趣的人)的标签问题现在位于metameta.vi.stackexchange.com/questions/1229/……