内置的VIM :sort
命令可对文本行进行排序.我想在一行中对单词进行排序,例如变换行
b a d c e f
至
a b c d e f
目前我通过选择线然后使用来实现这一点:!tr ' ' '\n' | sort | tr '\n' ' '
,但我确信有更好,更简单,更快捷的方式.在那儿?
请注意,我使用bash,所以如果有一个更短更优雅的bash命令来执行此操作,那也没关系.
编辑:我的用例是我有一行说SOME_VARIABLE="one two three four etc"
,我想要对该变量中的单词进行排序,即我想要SOME_VARIABLE="etc four one three two"
.
最终结果应该优选地可以映射到快捷键,因为这是我经常需要的东西.
在纯vim中,你可以这样做:
call setline('.', join(sort(split(getline('.'), ' ')), " "))
编辑
要做到这一点,使它在小于一行的范围内工作稍微复杂一点(这允许单独排序多行或排序一行的一部分,具体取决于视觉选择):
command! -nargs=0 -range SortWords call SortWords() " Add a mapping, go to your string, then press vi",s " vi" selects everything inside the quotation " ,s calls the sorting algorithm vmap ,s :SortWords" Normal mode one: ,s to select the string and sort it nmap ,s vi",s function! SortWords() " Get the visual mark points let StartPosition = getpos("'<") let EndPosition = getpos("'>") if StartPosition[0] != EndPosition[0] echoerr "Range spans multiple buffers" elseif StartPosition[1] != EndPosition[1] " This is a multiple line range, probably easiest to work line wise " This could be made a lot more complicated and sort the whole " lot, but that would require thoughts on how many " words/characters on each line, so that can be an exercise for " the reader! for LineNum in range(StartPosition[1], EndPosition[1]) call setline(LineNum, join(sort(split(getline('.'), ' ')), " ")) endfor else " Single line range, sort words let CurrentLine = getline(StartPosition[1]) " Split the line into the prefix, the selected bit and the suffix " The start bit if StartPosition[2] > 1 let StartOfLine = CurrentLine[:StartPosition[2]-2] else let StartOfLine = "" endif " The end bit if EndPosition[2] < len(CurrentLine) let EndOfLine = CurrentLine[EndPosition[2]:] else let EndOfLine = "" endif " The middle bit let BitToSort = CurrentLine[StartPosition[2]-1:EndPosition[2]-1] " Move spaces at the start of the section to variable StartOfLine while BitToSort[0] == ' ' let BitToSort = BitToSort[1:] let StartOfLine .= ' ' endwhile " Move spaces at the end of the section to variable EndOfLine while BitToSort[len(BitToSort)-1] == ' ' let BitToSort = BitToSort[:len(BitToSort)-2] let EndOfLine = ' ' . EndOfLine endwhile " Sort the middle bit let Sorted = join(sort(split(BitToSort, ' ')), ' ') " Reform the line let NewLine = StartOfLine . Sorted . EndOfLine " Write it out call setline(StartPosition[1], NewLine) endif endfunction
使用你的答案中的好主意,尤其是Al的答案,我最终想出了以下内容:
:vnoremapd:execute 'normal i' . join(sort(split(getreg('"'))), ' ')
这会F2在visual
模式下映射按钮以删除所选文本,拆分,排序和连接,然后重新插入.当选择跨越多行时,这将对所有单词中的单词进行排序并输出一个排序的行,我可以使用它快速修复gqq
.
我很高兴听到有关如何进一步改进的建议.
非常感谢,我学到了很多:)
编辑:更改'
为getreg('"')
处理带有字符的文本'
.
这是纯vimscript中的等价物:
:call setline('.',join(sort(split(getline('.'),' ')),' '))
它不会更短或更简单,但如果这是您经常做的事情,您可以在一系列行中运行它:
:%call setline('.',join(sort(split(getline('.'),' ')),' '))
或者发一个命令
:command -nargs=0 -range SortLine, call setline('.',join(sort(split(getline('.'),' ')),' '))
您可以使用哪个
:SortLine :'<,'>SortLine :%SortLine
等等
:!perl -ne '$,=" ";print sort split /\s+/'
不确定是否需要解释,但如果是:
perl -ne ''
为输入中的每一行运行''内的任何内容 - 将该行放在默认变量$ _中.
$,=" ";
将列表输出分隔符设置为空格.例如:
=> perl -e 'print 1,2,3' 123 => perl -e '$,=" ";print 1,2,3' 1 2 3 => perl -e '$,=", ";print 1,2,3' 1, 2, 3
很简单.
print sort split /\s+/
缩短版本:
print( sort( split( /\s+/, $_ ) ) )
($ _结尾是默认变量).
split - 使用给定的regexp将$ _拆分为数组,对给定列表进行排序,打印 - 打印它.