Skip to content
This repository

Dollar escape #1025

Merged
merged 3 commits into from over 2 years ago

2 participants

Thomas Kluyver Min RK
Thomas Kluyver
Collaborator

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.

Min RK
Owner

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.

Thomas Kluyver
Collaborator

Yep, good idea. Done.

Min RK
Owner

Thanks, I say go ahead and merge.

Thomas Kluyver takluyver merged commit aa30a66 into from November 22, 2011
Thomas Kluyver takluyver closed this November 22, 2011
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/test_interactiveshell.py
@@ -201,7 +201,10 @@ def test_drop_by_id(self):
201 201
 
202 202
     def test_var_expand(self):
203 203
         ip = get_ipython()
204  
-        ip.user_ns['f'] = 'Ca\xc3\xb1o'
  204
+        ip.user_ns['f'] = u'Ca\xf1o'
  205
+        self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
  206
+
  207
+        ip.user_ns['f'] = b'Ca\xc3\xb1o'
205 208
         # This should not raise any exception:
206 209
         ip.var_expand(u'echo $f')
207 210
 
4  IPython/utils/tests/test_text.py
@@ -107,3 +107,7 @@ def test_dollar_formatter():
107 107
     nt.assert_equals(s, "12")
108 108
     s = f.format("$n/{stuff[:5]}", **ns)
109 109
     nt.assert_equals(s, "12/hello")
  110
+    s = f.format("$n $$HOME", **ns)
  111
+    nt.assert_equals(s, "12 $HOME")
  112
+    s = f.format("${foo}", foo="HOME")
  113
+    nt.assert_equals(s, "$HOME")
12  IPython/utils/text.py
@@ -663,20 +663,26 @@ class DollarFormatter(FullEvalFormatter):
663 663
     In [4]: f.format('$a or {b}', a=1, b=2)
664 664
     Out[4]: u'1 or 2'
665 665
     """
666  
-    _dollar_pattern = re.compile("(.*)\$([\w\.]+)")
  666
+    _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
667 667
     def parse(self, fmt_string):
668 668
         for literal_txt, field_name, format_spec, conversion \
669 669
                     in Formatter.parse(self, fmt_string):
670 670
             
671 671
             # Find $foo patterns in the literal text.
672 672
             continue_from = 0
  673
+            txt = ""
673 674
             for m in self._dollar_pattern.finditer(literal_txt):
674 675
                 new_txt, new_field = m.group(1,2)
675  
-                yield (new_txt, new_field, "", None)
  676
+                # $$foo --> $foo
  677
+                if new_field.startswith("$"):
  678
+                    txt += new_txt + new_field
  679
+                else:
  680
+                    yield (txt + new_txt, new_field, "", None)
  681
+                    txt = ""
676 682
                 continue_from = m.end()
677 683
             
678 684
             # Re-yield the {foo} style pattern
679  
-            yield (literal_txt[continue_from:], field_name, format_spec, conversion)
  685
+            yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
680 686
 
681 687
 
682 688
 def columnize(items, separator='  ', displaywidth=80):
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.