{"id":62,"date":"2011-12-29T14:14:00","date_gmt":"2011-12-29T14:14:00","guid":{"rendered":"https:\/\/sandrock.co.za\/carl\/2011\/12\/29\/the-fallacy-of-the-general-purpose-tool\/"},"modified":"2026-08-11T06:42:24","modified_gmt":"2026-08-11T04:42:24","slug":"the-fallacy-of-the-general-purpose-tool","status":"publish","type":"post","link":"https:\/\/sandrock.co.za\/carl\/2011\/12\/the-fallacy-of-the-general-purpose-tool\/","title":{"rendered":"The fallacy of the general purpose tool"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I carry a Leatherman on my belt every day wherever I go. It has become a bit of an extension of my body, which I only really notice when I have to fly somewhere and I&#8217;m forced to take it off for the flight. Then I get to my destination and I can&#8217;t open the cable ties on my luggage. At the same time, I have a whole pinboard of tools up in my garage, which overlap somewhat with my Leatherman: a dedicated set of pliers, some dedicated screwdrivers and scissors and so on. This is because the Leatherman is not as good as any of these dedicated tools.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I think the same goes for programming languages, and therefore I have learned quite a few, just like I have stocked my pinboard with tools that do one thing very well.  Many people find learning new languages onerous and will try to find the one language that does everything they want to do well. Their arguments against learning a new language often involves something like &#8220;but I can do that just fine in my language, and then I don&#8217;t have to learn a new language&#8221;.  Here&#8217;s an example from real life that illustrates the advantages of special purpose languages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">My father approaches me with this problem. He uses an accounting package which can import <a href=\"http:\/\/www.ofx.net\/\">OFX files<\/a> (they&#8217;re an SGML\/XML format for financial records), but there is a slight problem. The ZAR needs to be changed to USD and the dates (which are tags of the form <code>&lt;DT20111201><\/code> &#8211; yes, no closing tag as it&#8217;s SGML) have to be changed from YYYYMMDD to YYYYDDMM. Now, turns out that Python has a nice OFX module. So does <a href=\"http:\/\/ofx4j.sourceforge.net\/\">Java<\/a>. But the fastest way to make the changes to his files is probably sed:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-Fira-Code\" style=\"font-size:.875rem;font-family:Code-Pro-Fira-Code,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#839496;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sed -r -i -e 's\/ZAR\/USD\/' -e 's\/&lt;DT(.*)>&lt;dt>&lt;\/dt>&lt;dt>(&#91;0-9&#93;{4})(&#91;0-9&#93;{2})(&#91;0-9&#93;{2})\/&lt;DT\\1>\\2\\4\\3\/' filename.ocx&lt;\/dt><\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki solarized-dark\" style=\"background-color: #002B36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #839496\">sed <\/span><span style=\"color: #859900\">-<\/span><span style=\"color: #839496\">r <\/span><span style=\"color: #859900\">-<\/span><span style=\"color: #839496\">i <\/span><span style=\"color: #859900\">-<\/span><span style=\"color: #839496\">e <\/span><span style=\"color: #2AA198\">&#39;s\/ZAR\/USD\/&#39;<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #859900\">-<\/span><span style=\"color: #839496\">e <\/span><span style=\"color: #2AA198\">&#39;s\/&lt;DT(.*)&gt;&lt;dt&gt;&lt;\/dt&gt;&lt;dt&gt;(&#91;0-9&#93;<\/span><span style=\"color: #CB4B16\">{4}<\/span><span style=\"color: #2AA198\">)(&#91;0-9&#93;<\/span><span style=\"color: #CB4B16\">{2}<\/span><span style=\"color: #2AA198\">)(&#91;0-9&#93;<\/span><span style=\"color: #CB4B16\">{2}<\/span><span style=\"color: #2AA198\">)\/&lt;DT<\/span><span style=\"color: #CB4B16\">\\1<\/span><span style=\"color: #2AA198\">&gt;<\/span><span style=\"color: #CB4B16\">\\2\\4\\3<\/span><span style=\"color: #2AA198\">\/&#39;<\/span><span style=\"color: #839496\"> filename.ocx<\/span><span style=\"color: #859900\">&lt;\/<\/span><span style=\"color: #839496\">dt<\/span><span style=\"color: #859900\">&gt;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">This does the replacement in-place, is really fast and is quick enough to throw together.  This is the kind of thing that sed shines at.  In fact, it is exactly what it was designed to do, so it is unsurprising that it does it so well.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To do the same thing in Python (even without using the OFX module) requires a bit more effort:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-Fira-Code\" style=\"font-size:.875rem;font-family:Code-Pro-Fira-Code,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#839496;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>import os\nimport re\nfrom tempfile import mkstemp\n\nfilename = \"test.txt\"\npatternStrings = [\"ZAR\", r\"&lt;TD(&#91;^>&#93;+)>(&#91;0-9&#93;{4})(&#91;0-9&#93;{2})(&#91;0-9&#93;{2})\"]\nreplacements = &#91;\"USD\", r\"&lt;TD\\1>\\2\\4\\3\"&#93;\n\n# Compile patterns\npatterns = &#91;re.compile(p) for p in patternStrings&#93;\n\n# Create temporary file to hold outputs\n_, tempfile = mkstemp()\n\n# Process file\noutfile = open(tempfile, 'w')\nfor line in open(filename):\n    for pattern, replacement in zip(patterns, replacements):\n        line = pattern.sub(replacement, line)\n    outfile.write(line)\n\noutfile.close()\n\nos.rename(tempfile, filename)\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki solarized-dark\" style=\"background-color: #002B36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> os<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> re<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">from<\/span><span style=\"color: #839496\"> tempfile <\/span><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> mkstemp<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">filename <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #2AA198\">&quot;test.txt&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">patternStrings <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> [<\/span><span style=\"color: #2AA198\">&quot;ZAR&quot;<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #93A1A1; font-weight: bold\">r<\/span><span style=\"color: #DC322F\">&quot;&lt;TD(<\/span><span style=\"color: #CB4B16\">&#91;<\/span><span style=\"color: #859900\">^<\/span><span style=\"color: #CB4B16\">&gt;&#93;<\/span><span style=\"color: #859900\">+<\/span><span style=\"color: #DC322F\">)&gt;(<\/span><span style=\"color: #CB4B16\">&#91;0-9&#93;<\/span><span style=\"color: #859900\">{4}<\/span><span style=\"color: #DC322F\">)(<\/span><span style=\"color: #CB4B16\">&#91;0-9&#93;<\/span><span style=\"color: #859900\">{2}<\/span><span style=\"color: #DC322F\">)(<\/span><span style=\"color: #CB4B16\">&#91;0-9&#93;<\/span><span style=\"color: #859900\">{2}<\/span><span style=\"color: #DC322F\">)&quot;<\/span><span style=\"color: #839496\">]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">replacements <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> &#91;<\/span><span style=\"color: #2AA198\">&quot;USD&quot;<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #93A1A1; font-weight: bold\">r<\/span><span style=\"color: #DC322F\">&quot;&lt;TD<\/span><span style=\"color: #268BD2\">\\1<\/span><span style=\"color: #DC322F\">&gt;<\/span><span style=\"color: #268BD2\">\\2\\4\\3<\/span><span style=\"color: #DC322F\">&quot;<\/span><span style=\"color: #839496\">&#93;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #586E75; font-style: italic\"># Compile patterns<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">patterns <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> &#91;re.compile(p) <\/span><span style=\"color: #859900\">for<\/span><span style=\"color: #839496\"> p <\/span><span style=\"color: #859900\">in<\/span><span style=\"color: #839496\"> patternStrings&#93;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #586E75; font-style: italic\"># Create temporary file to hold outputs<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">_, tempfile <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> mkstemp()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #586E75; font-style: italic\"># Process file<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">outfile <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">open<\/span><span style=\"color: #839496\">(tempfile, <\/span><span style=\"color: #2AA198\">&#39;w&#39;<\/span><span style=\"color: #839496\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">for<\/span><span style=\"color: #839496\"> line <\/span><span style=\"color: #859900\">in<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">open<\/span><span style=\"color: #839496\">(filename):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    <\/span><span style=\"color: #859900\">for<\/span><span style=\"color: #839496\"> pattern, replacement <\/span><span style=\"color: #859900\">in<\/span><span style=\"color: #839496\"> <\/span><span style=\"color: #268BD2\">zip<\/span><span style=\"color: #839496\">(patterns, replacements):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        line <\/span><span style=\"color: #859900\">=<\/span><span style=\"color: #839496\"> pattern.sub(replacement, line)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    outfile.write(line)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">outfile.close()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">os.rename(tempfile, filename)<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Needless to say, the difference is even more pronounced in Java due to the large amount of boilerplate needed.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-Fira-Code\" style=\"font-size:.875rem;font-family:Code-Pro-Fira-Code,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#839496;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>import java.io.File;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.util.Scanner;\nimport java.util.regex.Pattern;\n\npublic class Fixer {\n    static File infile = new File(\"test.txt\");\n    static String[] patternStrings = {\"ZAR\", \"&lt;TD(&#91;^>&#93;*)>(&#91;0-9&#93;{4})(&#91;0-9&#93;{2})(&#91;0-9&#93;{2})\"};\n    static String[] replacementStrings = {\"USD\", \"&lt;TD$1>$2$4$3\"};\n\n    public static void main(String[] args) throws IOException {\n        Pattern[] patterns = new Pattern&#91;patternStrings.length&#93;;\n        Scanner in = new Scanner(new FileReader(infile));\n        \n        \/\/ Compile patterns\n        for (int i=0; i&lt;patternStrings.length; i++) {\n            patterns&#91;i&#93; = Pattern.compile(patternStrings&#91;i&#93;);\n        }\n        \n        \/\/ Create temporary file to hold outputs\n        File tempfile = File.createTempFile(\"tmp\", \"tmp\");\n\n        \/\/ Process file\n        FileWriter outfile = new FileWriter(tempfile);\n        while (in.hasNextLine()) {\n            String line = in.nextLine();\n            for (int i=0; i &lt; patterns.length; i++)\n                line = patterns&#91;i&#93;.matcher(line).replaceAll(replacementStrings&#91;i&#93;);\n            \n            outfile.write(line + System.getProperty(\"line.separator\"));\n        }        \n        outfile.close();\n        \n        \/\/ move temp file back to filename\n        tempfile.renameTo(infile);\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki solarized-dark\" style=\"background-color: #002B36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> java.io.File;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> java.io.FileReader;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> java.io.FileWriter;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> java.io.IOException;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> java.util.Scanner;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #859900\">import<\/span><span style=\"color: #839496\"> java.util.regex.Pattern;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">public <\/span><span style=\"color: #93A1A1; font-weight: bold\">class<\/span><span style=\"color: #839496\"> Fixer {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    static File infile = new File(<\/span><span style=\"color: #2AA198\">&quot;test.txt&quot;<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    static String[] patternStrings = {<\/span><span style=\"color: #2AA198\">&quot;ZAR&quot;<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #2AA198\">&quot;&lt;TD(&#91;^&gt;&#93;*)&gt;(&#91;0-9&#93;<\/span><span style=\"color: #CB4B16\">{4}<\/span><span style=\"color: #2AA198\">)(&#91;0-9&#93;<\/span><span style=\"color: #CB4B16\">{2}<\/span><span style=\"color: #2AA198\">)(&#91;0-9&#93;<\/span><span style=\"color: #CB4B16\">{2}<\/span><span style=\"color: #2AA198\">)&quot;<\/span><span style=\"color: #839496\">};<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    static String[] replacementStrings = {<\/span><span style=\"color: #2AA198\">&quot;USD&quot;<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #2AA198\">&quot;&lt;TD$1&gt;$2$4$3&quot;<\/span><span style=\"color: #839496\">};<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    public static void main(String[] args) throws IOException {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        Pattern[] patterns = new Pattern&#91;patternStrings.length&#93;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        Scanner <\/span><span style=\"color: #859900\">in<\/span><span style=\"color: #839496\"> = new Scanner(new FileReader(infile));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #859900\">\/\/<\/span><span style=\"color: #839496\"> Compile patterns<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #859900\">for<\/span><span style=\"color: #839496\"> (<\/span><span style=\"color: #859900\">int<\/span><span style=\"color: #839496\"> i=<\/span><span style=\"color: #D33682\">0<\/span><span style=\"color: #839496\">; i<\/span><span style=\"color: #859900\">&lt;<\/span><span style=\"color: #839496\">patternStrings.length; i<\/span><span style=\"color: #DC322F\">++<\/span><span style=\"color: #839496\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            patterns&#91;i&#93; = Pattern.compile(patternStrings&#91;i&#93;);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #859900\">\/\/<\/span><span style=\"color: #839496\"> Create temporary file to hold outputs<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        File tempfile = File.createTempFile(<\/span><span style=\"color: #2AA198\">&quot;tmp&quot;<\/span><span style=\"color: #839496\">, <\/span><span style=\"color: #2AA198\">&quot;tmp&quot;<\/span><span style=\"color: #839496\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #859900\">\/\/<\/span><span style=\"color: #839496\"> Process file<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        FileWriter outfile = new FileWriter(tempfile);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #859900\">while<\/span><span style=\"color: #839496\"> (<\/span><span style=\"color: #859900\">in<\/span><span style=\"color: #839496\">.hasNextLine()) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            String line = <\/span><span style=\"color: #859900\">in<\/span><span style=\"color: #839496\">.nextLine();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><span style=\"color: #859900\">for<\/span><span style=\"color: #839496\"> (<\/span><span style=\"color: #859900\">int<\/span><span style=\"color: #839496\"> i=<\/span><span style=\"color: #D33682\">0<\/span><span style=\"color: #839496\">; i <\/span><span style=\"color: #859900\">&lt;<\/span><span style=\"color: #839496\"> patterns.length; i<\/span><span style=\"color: #DC322F\">++<\/span><span style=\"color: #839496\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">                line = patterns&#91;i&#93;.matcher(line).replaceAll(replacementStrings&#91;i&#93;);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            <\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">            outfile.write(line <\/span><span style=\"color: #859900\">+<\/span><span style=\"color: #839496\"> System.getProperty(<\/span><span style=\"color: #2AA198\">&quot;line.separator&quot;<\/span><span style=\"color: #839496\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        }        <\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        outfile.close();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        <\/span><span style=\"color: #859900\">\/\/<\/span><span style=\"color: #839496\"> move temp file back to filename<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">        tempfile.renameTo(infile);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #839496\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Now, at this point someone is bound to say &#8220;but wait, people don&#8217;t write desktop apps in sed!&#8221;.  But that&#8217;s quite the point &#8211; Java was designed with programming in the large in mind, but it is really tedious for short programs.  In many cases, learning a small domain specific language and using it to solve your small problem is faster than learning how to do the same thing in your &#8220;one language&#8221;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I wish I had more time to put examples together, but this situation just presented itself and got me thinking.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I carry a Leatherman on my belt every day wherever I go. It has become a bit of an extension of my body, which I only really notice when I have to fly somewhere and I&#8217;m forced to take it off for the flight. Then I get to my destination and I can&#8217;t open the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[3],"tags":[187],"class_list":["post-62","post","type-post","status-publish","format-standard","hentry","category-programming","tag-ramble"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts\/62","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/comments?post=62"}],"version-history":[{"count":2,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts\/62\/revisions"}],"predecessor-version":[{"id":321,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/posts\/62\/revisions\/321"}],"wp:attachment":[{"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/media?parent=62"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/categories?post=62"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sandrock.co.za\/carl\/wp-json\/wp\/v2\/tags?post=62"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}