About | Links | Scripts
Sharing linux/windows scripts and tips

Vim Odd Jobs 1

March 30, 2019 — Jesse Harris

Today Clarissa did the shopping and as she was in a rush didn't have the time to total the items in the trolley. She had updated the cost of each item in a shared iCloud note and texted me to see if I could quickly add them up on my computer.

This is the point where most people would pull out calc.exe and manually sum them. Not I!.

I fired up the iCloud site on my machine and copy and pasted the iCloud note to a fresh vim buffer:

    Shopping 2019
    1st Isle:
    Potatoes 4 + 6 6 3 3 5 16.99 2 2 3 3 4.99 5.99 5.99 5.99 12.15 7.99 7.99 8.99
    Other vedge for a meat + vedge dinner
    Chicken dinner with a sauce (Indian or Apricot or some other chicken + rice meal)
    Lunch Chicken
    Kids Junk Food
    Tiny Teddies (Olivia’s request) 2.49 2.49
    Flavoured Rice Cakes 6
    Crackers 2.49 2.49
    Dairy 2.69
    Big tub of greek yogurt
    Vanilla Bean Yogurt 3.99 3.99 3.99
    Butter  - 4.99 4.99 4.99
    Milk Powder  - 5.69 5.69 5.69
    Second Isle
    Corn Chips for Nachos
    Nacho Salsa
    Popcorn 2.49 2.49 9.98
    A Cordial or somesuch 2.49
    Third Isle
    Pies 3.55 3
    Lasagne? 12
    French Fires 1.89 1.89
    Chicken Nuggets 2.99 2.99
    Garbage Bags 1.79
    Mozzie Coils
    Last Isle
    Spaghetti Pasta .65 .65 1.59 1.59
    Tinned Beetroot 1.15
    Tinned Spagetti * .85 .85 .85
    Indian or rice meal sauce 2.49 .99
    Soap 1.99 3.49
    Brown Sugar 2.69
    Bread 1.25 1.25
    Wraps 1.95 1.95
    1.99 1.99 1.99

My thought was this:

  • Do a search and replace on everything bar the numbers
  • Quickly tally the numbers using bc

Step 1. Find the search

Best way to figure out a regular expression in vim is to enable these two settings:

    :set hlsearch incsearch

With these set, you can begin a search by typing / then as you type results are instantly highlighted.

After a few tries with negative lookbehinds and whatnot, I settled on this:

    /\v[a-zA-Z()+*?\- :]

The \v causes Vim to use a more modern regex pattern requiring far less escape characters.

Run the search

I then ran the search of the whole file:

    :%s/\v[a-zA-Z()+*?\- :]/ /g

Then all I had to do was clean up double spaces and the blank lines

    :%s/\v^\s+//g    " removing leading spaces
    :g/\v^$/d        " delete blank lines

Convert it to a format that bc would like

    :%s/\v\s/+/g     " replace spaces with +
    :%s/\v\n/+/g     " replace newlines with +
    :%s/\v\+$//g     " remove any trailing +'s

Tally with BC

You can do this from within Vim using the ! command or drop the shell and do it

    :!cat % | bc

Now all that may seem a little over the top for tallying a shopping list, however it's little exercises like this that can help you learn more vim, regex, shell and other useful things

Extra credit

You could of course you another tool to add the numbers up. Here is how to do it using awk having each number on a seperate line:

    :!awk '{n+=$1}; END{print n}' %

Using powershell each number on seperate line

    :!pwsh -com "&{gc %|\%{[double]\$n+=\$_};\$n}"

Credit for awk and bc goes to this askubuntu answer.

Tags: vim-tips, vim-odd-jobs