Quote shell characters

Sometimes it’s nice to be able to display a command being run and do it in a form that can be repeated from a terminal window. Unfortunately, I’ll build a command in python like this:

args = ['somecmd', 'WHERE=$(DESTDIR)', '--message', "Lot's of text" ]

The trivial answer of ‘ ‘.join (args) produces something that can’t be passed to the shell:

>>> ' '.join (args)
"somecmd WHERE=$(DESTDIR) --message Lot's of text"

Here is a code fragment and some attached tests that provide better quoting. It’s used like this:

>>> import shquote
>>> args = ['somecmd', 'WHERE=$(DESTDIR)', '--message', "Lot's of text" ]
>>> print ' '.join ([shquote.shquote (a) for a in args])
somecmd 'WHERE=$(DESTDIR)' --message "Lot's of text"
#!/usr/bin/env python
def shquote (arg):
    """
    Quote a single argument in the most readable way so it is safe from
    shell expansion.
    """
    # Return an empty string as double quoted
    if not arg:
        return '""'
    special = """ t[]{}()'*?|;"""   # These need double quotes
    superspecial = """$"!"""        # These need single quotes
    quotechar = None
    # See if we need single quotes
    for c in superspecial:
        if c in arg:
            quotechar = "'"
            break
    # See if we need double quotes
    if not quotechar:
        for c in special:
            if c in arg:
                quotechar = '"'
                break
    # No quoting necessary
    if not quotechar:
        return arg
    # If quotechar is present then escape it by dropping out of quotes
    if quotechar in arg:
        arg = arg.replace (quotechar, "%s\%s%s" % (quotechar, quotechar, quotechar))
    return quotechar + arg + quotechar
if __name__ == '__main__':
    tests = [('',       '""'),
             ('*.cpp',  '"*.cpp"'),
             ('test.[ch]', '"test.[ch]"'),
             ('(',      '"("'),
             (')',      '")"'),
             ('a',      'a'),
             ('$',      """'$'"""),
             ('$a',     """'$a'"""),
             ('abc|def', '"abc|def"'),
             ('abc;def', '"abc;def"'),
             ('a b',    '"a b"'),
             ('"abc"',  """'"abc"'"""),
             ("""It's mine""", '"It's mine"'),
             ('abc | def ABC=$(XYC)', """'abc | def ABC=$(XYC)'"""),
             (""""That's impossible!" he said.""", """'"That'\''s impossible!" he said.'"""),
          ]
    for (input, expected) in tests:
        output = shquote (input)
        if output != expected:
            print 'input    = ', input
            print 'expected = ', expected
            print 'got      = ', output
        else:
            print "%-30s => %s" % (input, output)

And the result of running this:

bash-3.2$ ./shquote.py
                               => ""
*.cpp                          => "*.cpp"
test.[ch]                      => "test.[ch]"
(                              => "("
)                              => ")"
a                              => a
$                              => '$'
$a                             => '$a'
abc|def                        => "abc|def"
abc;def                        => "abc;def"
a b                            => "a b"
"abc"                          => '"abc"'
It's mine                      => "It's mine"
abc | def ABC=$(XYC)           => 'abc | def ABC=$(XYC)'
"That's impossible!" he said.  => '"That'''s impossible!" he said.'

Passing extra arguments to output operator

I usually implement the output operator for a class, operator<<().
I find it useful for debugging and regression testing purposes.
Occasionally when defining a class hierarchy with polymorphism in mind
I’ll instead define a virtual print() method.

Base  base;
std::cout << "base = " << base << std::endl;

Here’s the typical implementation:

class Base {
// ...
public:
    /// print Base with flags indicating hw much extra to include
    virtual void print (std::ostream &out, int flags);
};
std::ostream &
operator<< (std::ostream &out, const Base &base)
{
    base.print (out, 0);
}

So everything is great except… I now want to pass that extra
argument. I could write the following ugly code:

std::cout << "base = ";
base.print (std::cout, 1);
std::cout << std::endl;

Instead, I’m going to follow the example from <iomanip> and define a struct
that saves the arguments and then define an output operator for that
struct. The following code makes it so you can write the above as:

std::cout << "base = " << printstream (base, 1) << std::endl;

Here is the implementation of that. This expects the class to implement a method print() that takes a std::ostream and a second argument. It’s pretty easy to extend this to a print() that takes a third argument.

#ifndef INCLUDED_PRINTSTREAM_H
#define INCLUDED_PRINTSTREAM_H
#include 
namespace printstream_impl {
template
struct PrintStream1
{
    const ObjectType &  m_object;
    const Arg1Type &    m_arg1;
    PrintStream1 (const ObjectType &object, const Arg1Type &arg1)
        : m_object (object),
          m_arg1 (arg1)
    {
    }
    std::ostream &print (std::ostream &out) const
    {
        m_object.print (out, m_arg1);
        return out;
    }
};
template
std::ostream &operator<<(std::ostream &out, const PrintStream1 &ps)
{
    ps.print (out);
    return out;
}
} // End namespace printstream
template
printstream_impl::PrintStream1
printstream (const ObjectType &object,
             const Arg1Type &arg1)
{
    return printstream_impl::PrintStream1 (object, arg1);
}
#endif /*  INCLUDED_PRINTSTREAM_H */

Switching keys in values in a map

A functor that reverses a pair: first becomes second,
second becomes first. Useful for switching
from a map to another map (or multimap in this example) where
the value becomes the key and the key the value.

std::map<std::string, int> m;
std::multimap<int,std::string> m2;
m["a"] = 0;
m["b"] = 1;
m["c"] = 0;
std::transform (m.begin(), m.end(), std::inserter (m2, m2.begin()),
                pair_switch());

And the actual code:

template<class PairType>
struct pair_switcher : public std::unary_function<PairType, std::pair<a,b>
{
 typedef std::pair result_type;
 typedef PairType argument_type;
 result_type operator()(const argument_type &p) const
 {
     return result_type (p.second, p.first);
 }
};

Functor for deleting objects

In a destructor for a class, I had a std::vector of pointers that I wanted to delete. I started to write the usual for(;;) loop and realized I do this often enough I should make it easy to use std::for_each().
Here’s the functor (based on std::unary_function):

template
struct deleter: public std::unary_function
{
    bool operator()(Type * ptr) const
    {
        delete ptr;
        return true;
    }
};

And here’s some sample code using it:

std::vector m_symbols;
// ...
std::for_each (m_symbols.begin(), m_symbols.end(), deleter());

I added a return of true because some other template code wasn’t happy about “return void” — supposedly something fixed in recent compilers.