Hi eveyone. I am trying to read a file using vi editor and sort its content inside the file alphabetically which is only names on CAPITAL LETTERS, second field (JOHN, MIKE, JAYSON and TYLER).
The file is smth like this inside:
1:JOHN:Morgan:90:24
2:MIKE:Smith:95:11
3:JAYSON:Ty:99:9
4:TYLER:Edward:89:5

This is my vi script:

file="/home/students/domie/wine.txt"
while IFS=: read -r f1 f2 f3 f4 f5
do
        tput cup $f1 0 ;echo  "$f2 $f1 $f3 $f4 $f5"
done <"$file"

I came up to here to sort them, but this only switches places of f2 with f1.
Can someone help me?
thank you

Dani AI

Generated

Short, practical summary that builds on 's suggestion and on your script, .

Your while-read loop prints each record as it reads them, so trying to "sort" inside that loop won't reorder the file lines — do the sort before you print (or let the editor reorder lines). For a reliable, locale-independent shell solution that sorts by the second colon-separated field (the ALL-CAPS names) and safely replaces the file:

LC_ALL=C sort -t: -k2,2 /home/students/domie/wine.txt > /tmp/wine.sorted && mv /tmp/wine.sorted /home/students/domie/wine.txt
  • -t: sets the colon as field separator.
  • -k2,2 uses only the second field as the sort key.
  • LC_ALL=C produces reproducible bytewise ordering.
    Always make a backup (e.g. cp wine.txt wine.txt.bak) before overwriting.

If you also want the first field renumbered sequentially after sorting (1..N), pipe through awk to set $1 = NR while preserving the other fields:

LC_ALL=C sort -t: -k2,2 /home/students/domie/wine.txt | awk -F: -v OFS=: '{$1 = NR; print}' > /tmp/wine.sorted && mv /tmp/wine.sorted /home/students/domie/wine.txt

If you prefer to stay inside Vim, use a regex key with :sort to sort on the second field, then optionally renumber the leading numeric IDs:

:%sort /\v^[^:]*:\zs[^:]*/
:%s/^\d\+/\=line('.')

The first command sorts by the second colon field (\zs marks the key start); the second replaces the leading digits with the current line number. Save with :w when done.

If you still want to place lines on specific screen rows with tput cup, run the sort first and then feed the sorted file to your display loop so the printed positions follow the sorted order.

Recommended Answers

All 3 Replies

edited

I've never really messed with vi/vim scripts, other than making a few minor modifications to my .vimrc startup file.

Using vim, you could sort the file using the command :sort.
That will sort the file in exactly the manner you have described. It's only a simple alphabetic sort, so there is no need to pass any parameters.
So you start with this:

JOHN:Morgan:90:24
MIKE:Smith:95:11
JAYSON:Ty:99:9
TYLER:Edward:89:5

Running the :sort command will give you this:

JAYSON:Ty:99:9
JOHN:Morgan:90:24
MIKE:Smith:95:11
TYLER:Edward:89:5

Which is what you wanted isn't it?

From the terminal or a shell-script, you could use the sort utility:
e.g. Sort the file and write the sorted output to a different file:
sort ./file.txt -o ./sorted.txt

But offhand, I'm not sure how you'd go about calling the sort function in a vi/vim script. I really should look into scripting vim though. I currently have a few macros set up in vim to automate various repetetive tasks. But it would be good to be able to write scripts for some of them!

thank you so much for the help

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.