Archive for November, 2011

I’m Wasting Time / Truncating Numbers with Regex

I’m Wasting Time

I waste too much time relearning how to do simple things that only come up once or twice per year. Some recent examples:

  • Figuring out how to build an AppleScript to show/hide hidden files. Every time I reinstall OS X I’m starting from scratch, with only a faint recollection that I once knew how to do this.
  • Every time I modify my /etc/hosts file I completely forget how to flush my local DNS. Sure the answer is a quick Google search away, but it’s frustrating that I can’t just remember this.
  • Once every 12 months or so I find myself needing to write a regex to truncate decimal numbers. This is trivial, but every time it comes up I have to spend thirty seconds thinking it through for like the tenth time in my life.

From this day forward, every time I learn (or re-learn) a simple task like this I’m going to document it on my blog. This is partially so that I can query my blog as a proxy for my past knowledge, but by making these little things public perhaps I can help somebody else also trying to relearn that little piece of syntax they once knew but forgot years ago.

Truncating Numbers with Regex

Today I was working with a JSON object containing SVG paths. The paths contain decimals with a ridiculous amount of precision and I needed a way to quickly truncate all of them at once. A portion of that file looked like this:

"frame" : {
"framePath" : "M 338.00358637178726,76.44431778009219C 337.3533534525326,76.44431778009219 328.2739344566734,75.22811129070296 319.67,74.15 C 317.50,73.88 295.21,70.88417372385919 293.094015386729,70.33711592961231 C 219.8144624861983,51.43448609977959 150.69444444444446,59.13249044730145 98.71787208607293,79.69548237636549 C 98.71787208607293,80.34571529562014 98.71787208607293,105.05456622729717 98.71787208607293,105.70479914655182 C 104.19818564217239,138.56241136723992 103.1188808312146,165.83046925594903 130.05909879414747,185.423355047173 C 171.04623388375416,215.2321805668871 230.55555555555557,210.52137933619036 259.1511450329329,197.25759417760776 C 274.12500192608155,190.31211676462385 284.23559266287486,174.83312522486972 297.3344728765868,163.7922732666347 ",
"nosePath" : "M 297.3344728765868,163.7922732666347C 300.61877960915047,157.71737810848663 299.45871165265066,156.9281764260582 303.90308634171424,151.64248295033855 C 312.8221414955163,141.03505334903969 324.94089906256886,132.40677608534708 338.00358637178726,131.06388299748352 ",
"templeProfilePath" : "M 103.39210998206816,86.42137601547572C 104.39210998206816,86.42137601547572 112.39210998206816,86.42137601547572 113.39210998206816,86.42137601547572 C 113.39210998206816,87.42137601547572 113.39210998206816,95.42137601547572 113.39210998206816,96.42137601547572 C 112.39210998206816,96.42137601547572 104.39210998206816,96.42137601547572 103.39210998206816,96.42137601547572 C 103.39210998206816,95.42137601547572 103.39210998206816,87.42137601547572 103.39210998206816,86.42137601547572 ",
"lensPath" : "M 304.6828883843359,94.28066353971869C 315.15242080095635,110.11085599156657 281.8913723752886,154.36727094138655 249.95695467226062,174.5634496818991 C 229.19157202630007,187.6960323215128 179.15619563044785,190.04204825863354 143.7124545468221,168.68589073225627 C 115.0311971938544,151.40437835918695 116.3066956065222,98.9434122137887 120.8796942175233,89.74067422456241 C 125.76091487574503,79.91766778910245 168.00571744139953,73.51652014971526 205.07771935487446,74.05426220951449 C 229.19157202630007,74.40404188517087 295.166110391501,79.8910593861534 304.6828883843359,94.28066353971869 "
}

So, I fired open my favorite text editor and built a regex to search for three groups in a row:

  • (\d+\.): A group of one or more digits ending with a period, followed by…
  • (\d{2}): a group of exactly two digits, followed by…
  • (\d*): a group of 0 or more digits

Altogether, the full regex search is:
(\d+\.)(\d{2})(\d*)

I wanted to keep the results of the first two groups, and ignore the last group, so my regex
replacement looked like this: $1$2

I know. It’s hardly rocket science. But now that it’s documented I’ll save myself 30 seconds every six months.

After running the regex find/replace my JSON shrunk to just this:

"frame" : {
"framePath" : "M 338.00,76.44C 337.35,76.44 328.27,75.22 319.67,74.15 C 317.50,73.88 295.21,70.88 293.09,70.33 C 219.81,51.43 150.69,59.13 98.71,79.69 C 98.71,80.34 98.71,105.05 98.71,105.70 C 104.19,138.56 103.11,165.83 130.05,185.42 C 171.04,215.23 230.55,210.52 259.15,197.25 C 274.12,190.31 284.23,174.83 297.33,163.79 ",
"nosePath" : "M 297.33,163.79C 300.61,157.71 299.45,156.92 303.90,151.64 C 312.82,141.03 324.94,132.40 338.00,131.06 ",
"templeProfilePath" : "M 103.39,86.42C 104.39,86.42 112.39,86.42 113.39,86.42 C 113.39,87.42 113.39,95.42 113.39,96.42 C 112.39,96.42 104.39,96.42 103.39,96.42 C 103.39,95.42 103.39,87.42 103.39,86.42 ",
"lensPath" : "M 304.68,94.28C 315.15,110.11 281.89,154.36 249.95,174.56 C 229.19,187.69 179.15,190.04 143.71,168.68 C 115.03,151.40 116.30,98.94 120.87,89.74 C 125.76,79.91 168.00,73.51 205.07,74.05 C 229.19,74.40 295.16,79.89 304.68,94.28 "
}

TextMate - Before Regex

TextMate - After Regex