sorting words

0 views
Skip to first unread message

MZ

unread,
Nov 20, 2008, 5:55:40 AM11/20/08
to vim_use
suppose I have a few line that goes like this:
str_list="foo bar man act"

how can I sort all the words within the quote “ ... " so that it
becomes "act bar foo man"? It is okay to eliminate extra whitespace so
that it ends up with only one space behind each word.

--MZ

Tim Chase

unread,
Nov 20, 2008, 6:16:46 AM11/20/08
to vim...@googlegroups.com

This is a common pattern of "decorate, sort, undecorate". In
this case the decoration is putting each word on its own line.
If it's long, you can readily do this with

1) issue

:s/\(\<\w\+\)\s*/\1\r/g

this should yield

str_list
="foo
bar
man
act
"

which you can hand-tweak to add one extra newline before "foo",
yielding

str_list
="
foo
bar
man
act
"

The aim in the first step is just to get each word on its own
line. If your string is short, it may be faster to do it by
hand. But if it's 20+ words in the string, using the regexp can
be faster.

2) highlight the range of words in the string and use

:'<,'>sort

to sort them

3) highlight the whole shebang and press J to rejoin them.

4) Clean up the extra space at the beginning and end of your
string (and optionally around the "=")

---------------

After typing the above, an alternative method (assuming you have
Vim7.0+) occurred to me, so you might also try

vi" visualize-inner-quotation
c change
^R= control+r = (expression register)
join(sort(split(@")), ' ')
the expression to split the deleted content
on whitespace, sort it, and join it back
together with a single space
<enter> accept the expression
<esc> leave insert-mode

If it's something you do frequently, it's easily mappable:

:nnoremap <f4> vi"c<c-r>=join(sort(split(@")), ' ')<cr><esc>
:vnoremap <f4> c<c-r>=join(sort(split(@")), ' ')<cr><esc>


Just a couple ideas -- use whichever works better for your needs
(or whichever you remember).

-tim


A. S. Budden

unread,
Nov 20, 2008, 6:17:23 AM11/20/08
to vim...@googlegroups.com
How about:

:g/str_list/let items = sort(copy(split(matchlist(getline('.'),
'"\([^"]*\)"')[1], ' \+'))) | s/"\zs[^"]*\ze"/\=join(items, ' ')

The above should be one line

:g/str_list/ " for all lines containing str_list
let items = " Assign to variable 'items'
sort( " Sort the list
copy( " Work on a copy of the list (:help sort())
split( " Split a string into parts (using delimiter ' \+')
matchlist( " Get a list of matches of a regular expression
getline('.') " Use the current line as the search fodder
'"\([^"]*\)"' " Search for a string of non-" characters inside double quotes
)[1] " Take the first match (everything inside the " ")
, ' \+') " See the split comment above
)) " End of sort/copy
| " THEN:
s/ " Substitute on the current line
"\zs[^"]\ze" " Match everything between the double quotes
\= " Expression replace
join(items, ' ') " Replace with a string comprising the sorted items

Al

2008/11/20 MZ <math...@gmail.com>:

Ulrich Mueller

unread,
Nov 20, 2008, 3:52:10 PM11/20/08
to vim...@googlegroups.com

To sort words within double quoted texts, try:

:%s/"\zs[^"]*\ze"/\=join(sort(split(submatch(0))))/g


On Thu, 20 Nov 2008, A. S. Budden wrote:
>
> How about:
>
> :g/str_list/let items = sort(copy(split(matchlist(getline('.'),
> '"\([^"]*\)"')[1], ' \+'))) | s/"\zs[^"]*\ze"/\=join(items, ' ')
>
> ...

MZ

unread,
Nov 21, 2008, 1:48:55 AM11/21/08
to vim_use
This is the exact command I used long ago but forgotten about.
Specifically I forgot about submatch(), and I thought \= was the
correct thing to use, but when I ran :h \= it was about something else
and I became unsure.

Thanks.

--MZ

On Nov 20, 12:52 pm, Ulrich Mueller <ulrich.muel...@hrz.tu-
chemnitz.de> wrote:
> To sort words within double quoted texts, try:
>
> :%s/"\zs[^"]*\ze"/\=join(sort(split(submatch(0))))/g
>
> On Thu, 20 Nov 2008, A. S. Budden wrote:
>
> > How about:
>
> > :g/str_list/let items = sort(copy(split(matchlist(getline('.'),
> > '"\([^"]*\)"')[1], ' \+'))) | s/"\zs[^"]*\ze"/\=join(items, ' ')
>
> > ...
>
> > 2008/11/20 MZ <mathf...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages