内置的VIM :sort命令可对文本行进行排序.我想在一行中对单词进行排序,例如变换行
b a d c e f
Run Code Online (Sandbox Code Playgroud)
至
a b c d e f
Run Code Online (Sandbox Code Playgroud)
目前我通过选择线然后使用来实现这一点:!tr ' ' '\n' | sort | tr '\n' ' ',但我确信有更好,更简单,更快捷的方式.在那儿?
请注意,我使用bash,所以如果有一个更短更优雅的bash命令来执行此操作,那也没关系.
编辑:我的用例是我有一行说SOME_VARIABLE="one two three four etc",我想要对该变量中的单词进行排序,即我想要SOME_VARIABLE="etc four one three two".
最终结果应该优选地可以映射到快捷键,因为这是我经常需要的东西.
DrA*_*rAl 23
在纯vim中,你可以这样做:
call setline('.', join(sort(split(getline('.'), ' ')), " "))
Run Code Online (Sandbox Code Playgroud)
编辑
要做到这一点,使它在小于一行的范围内工作稍微复杂一点(这允许单独排序多行或排序一行的一部分,具体取决于视觉选择):
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<CR>
" 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
Run Code Online (Sandbox Code Playgroud)
drr*_*lvn 14
使用你的答案中的好主意,尤其是Al的答案,我最终想出了以下内容:
:vnoremap <F2> d:execute 'normal i' . join(sort(split(getreg('"'))), ' ')<CR>
Run Code Online (Sandbox Code Playgroud)
这会F2在visual模式下映射按钮以删除所选文本,拆分,排序和连接,然后重新插入.当选择跨越多行时,这将对所有单词中的单词进行排序并输出一个排序的行,我可以使用它快速修复gqq.
我很高兴听到有关如何进一步改进的建议.
非常感谢,我学到了很多:)
编辑:更改'<C-R>"'为getreg('"')处理带有字符的文本'.
这是纯vimscript中的等价物:
:call setline('.',join(sort(split(getline('.'),' ')),' '))
Run Code Online (Sandbox Code Playgroud)
它不会更短或更简单,但如果这是您经常做的事情,您可以在一系列行中运行它:
:%call setline('.',join(sort(split(getline('.'),' ')),' '))
Run Code Online (Sandbox Code Playgroud)
或者发一个命令
:command -nargs=0 -range SortLine <line1>,<line2>call setline('.',join(sort(split(getline('.'),' ')),' '))
Run Code Online (Sandbox Code Playgroud)
您可以使用哪个
:SortLine
:'<,'>SortLine
:%SortLine
Run Code Online (Sandbox Code Playgroud)
等等
小智 6
:!perl -ne '$,=" ";print sort split /\s+/'
Run Code Online (Sandbox Code Playgroud)
不确定是否需要解释,但如果是:
perl -ne ''
Run Code Online (Sandbox Code Playgroud)
为输入中的每一行运行''内的任何内容 - 将该行放在默认变量$ _中.
$,=" ";
Run Code Online (Sandbox Code Playgroud)
将列表输出分隔符设置为空格.例如:
=> 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
Run Code Online (Sandbox Code Playgroud)
很简单.
print sort split /\s+/
Run Code Online (Sandbox Code Playgroud)
缩短版本:
print( sort( split( /\s+/, $_ ) ) )
Run Code Online (Sandbox Code Playgroud)
($ _结尾是默认变量).
split - 使用给定的regexp将$ _拆分为数组,对给定列表进行排序,打印 - 打印它.
也许你更喜欢 Python:
!python -c "import sys; print ' '.join(sorted(sys.stdin.read().split()))"
Run Code Online (Sandbox Code Playgroud)
视觉选择文本,并执行此行。