Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP


Dollar escape #1025

merged 3 commits into from

2 participants


As pointed out by @stefanv and @minrk on #822, it should be possible to use a raw $ in shell commands, e.g. for environment variables. This allows that, with the "$$HOME" syntax.


Looks good to me. Do you want to add a test to cover '${foo}' -> '$bar'? That's one probably quite rare use case that I've had to deal with long ago, where the shell variable name is a Python variable you want to expand. This works just fine right now with the syntax above, but we might add the test case anyway.


Yep, good idea. Done.


Thanks, I say go ahead and merge.

@takluyver takluyver merged commit aa30a66 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
5 IPython/core/tests/
@@ -201,7 +201,10 @@ def test_drop_by_id(self):
def test_var_expand(self):
ip = get_ipython()
- ip.user_ns['f'] = 'Ca\xc3\xb1o'
+ ip.user_ns['f'] = u'Ca\xf1o'
+ self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
+ ip.user_ns['f'] = b'Ca\xc3\xb1o'
# This should not raise any exception:
ip.var_expand(u'echo $f')
4 IPython/utils/tests/
@@ -107,3 +107,7 @@ def test_dollar_formatter():
nt.assert_equals(s, "12")
s = f.format("$n/{stuff[:5]}", **ns)
nt.assert_equals(s, "12/hello")
+ s = f.format("$n $$HOME", **ns)
+ nt.assert_equals(s, "12 $HOME")
+ s = f.format("${foo}", foo="HOME")
+ nt.assert_equals(s, "$HOME")
12 IPython/utils/
@@ -663,20 +663,26 @@ class DollarFormatter(FullEvalFormatter):
In [4]: f.format('$a or {b}', a=1, b=2)
Out[4]: u'1 or 2'
- _dollar_pattern = re.compile("(.*)\$([\w\.]+)")
+ _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
def parse(self, fmt_string):
for literal_txt, field_name, format_spec, conversion \
in Formatter.parse(self, fmt_string):
# Find $foo patterns in the literal text.
continue_from = 0
+ txt = ""
for m in self._dollar_pattern.finditer(literal_txt):
new_txt, new_field =,2)
- yield (new_txt, new_field, "", None)
+ # $$foo --> $foo
+ if new_field.startswith("$"):
+ txt += new_txt + new_field
+ else:
+ yield (txt + new_txt, new_field, "", None)
+ txt = ""
continue_from = m.end()
# Re-yield the {foo} style pattern
- yield (literal_txt[continue_from:], field_name, format_spec, conversion)
+ yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
def columnize(items, separator=' ', displaywidth=80):
Something went wrong with that request. Please try again.