8

Sorry if this post is a bit confusing to read this is my first post on this site and this is a hard question to ask, I have tried my best. I have also tried googling and i can not find anything.

I am trying to make my own command line like application in python and i would like to know how to split a string if a "\" is not in front of a space and to delete the backslash.

This is what i mean.

>>> c = "play song I\ Want\ To\ Break\ Free"
>>> print c.split(" ")
['play', 'song', 'I\\', 'Want\\', 'To\\', 'Break\\', 'Free']

When I split c with a space it keeps the backslash however it removes the space. This is how I want it to be like:

>>> c = "play song I\ Want\ To\ Break\ Free"
>>> print c.split(" ")
['play', 'song', 'I ', 'Want ', 'To ', 'Break ', 'Free']

If someone can help me that would be great!

Also if it needs Regular expressions could you please explain it more because I have never used them before.

Edit: Now this has been solved i forgot to ask is there a way on how to detect if the backslash has been escaped or not too?

1
  • I misread at first; you do want to split on spaces, but when a space is preceded by a backslash, you want to preserve the space as part of the split string. check. Commented Apr 18, 2014 at 17:46

3 Answers 3

14

It looks like you're writing a commandline parser. If that's the case, may I recommend shlex.split? It properly splits a command string according to shell lexing rules, and handles escapes properly. Example:

>>> import shlex
>>> shlex.split('play song I\ Want\ To\ Break\ Free')
['play', 'song', 'I Want To Break Free']
Sign up to request clarification or add additional context in comments.

3 Comments

BINGO! Exactly what I want! It even knows not to split if it's in quotes! Thanks. :) This is useful because it's going to be an input from raw_input() so if it has quotes then don't split! Thanks.
@aPyDeveloper: And I thought that you wanted to produce the demonstrated output! :-)
It has got the output I want
2

Just split on the space, then replace any string ending with a backslash with with one ending in a space instead:

[s[:-1] + ' ' if s.endswith('\\') else s for s in c.split(' ')]

This is a list comprehension; c is split on spaces, and each resulting string is examined for a trailing \ backslash at the end; if so, the last character is removed and a space is added.

One slight disadvantage: if the original string ends with a backslash (no space), that last backslash is also replaced by a space.

Demo:

>>> c = r"play song I\ Want\ To\ Break\ Free"
>>> [s[:-1] + ' ' if s.endswith('\\') else s for s in c.split(' ')]
['play', 'song', 'I ', 'Want ', 'To ', 'Break ', 'Free']

To handle escaped backslashes, you'd count the number of backslashes. An even number means the backslash is escaped:

[s[:-1] + ' ' if s.endswith('\\') and (len(s) - len(s.rstrip('\\'))) % 2 == 1 else s
 for s in c.split(' ')]

Demo:

>>> c = r"play song I\ Want\ To\ Break\\ Free"
>>> [s[:-1] + ' ' if s.endswith('\\') and (len(s) - len(s.rstrip('\\'))) % 2 == 1 else s
...  for s in c.split(' ')]
['play', 'song', 'I ', 'Want ', 'To ', 'Break\\\\', 'Free']

4 Comments

What does this do if the string ends in a backslash?
@WilliamKunkel: the last backslash is also replaced. Hrmz.
I have also just updated my questurn if you would like to help me on it too! ;)
@aPyDeveloper: You'd have to count the number of backslashes at the end of the string; if it is even then the backslash was escaped. len(s) - len(s.rstrip('\\')) would tell you how many backslashes there are at the end of the string.
0

Here's a noob one-liner no one has explored yet, that doesn't require any libraries. Note that you may use anything that is not already in the string instead of {{PlaceholderSpace}}:

s = 'play song I\ Want\ To\ Break\ Free'  
s = s.replace("\ ", "{{PlaceholderSpace}}")  # 'play song I{{PlaceholderSpace}}Want{{PlaceholderSpace}}To{{PlaceholderSpace}}Break{{PlaceholderSpace}}Free'  
l = s.split()  # ['play', 'song', 'I{{PlaceholderSpace}}Want{{PlaceholderSpace}}To{{PlaceholderSpace}}Break{{PlaceholderSpace}}Free']  
s = [e.replace("{{PlaceholderSpace}}", " ") for e in l]  # ['play', 'song', 'I Want To Break Free']  
  
# or in one-liner  
  
s = [e.replace("{{PlaceholderSpace}}", " ") for e in s.replace("\ ", "{{PlaceholderSpace}}").split()]  

1 Comment

I tend to use just {{}}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.