1

I have a string as follows

command= "copy1 "D:\path1\program Files" "c:\program Files\path1" copy2 "D:\path2\program Files" "c:\program Files\path2""

Note that both copy1 and copy2 are inside the string. My intention was to write each copy process insde an xml file as follows:

        <copyFiles>
               <copy1>
                    <Sourcepath>D:\path1\program Files</Sourcepath>
                    <DestPath>c:\program Files\path1</DestPath>
                </copy1>

                 <copy2>
                    <Sourcepath>D:\path2\program Files</Sourcepath>
                    <DestPath>c:\program Files\path2</DestPath>
                  </copy2>

         <copyFiles>

I tried to create a list of each paramter by splitting the string using spaces as follows:

Copyparamlist=command.split(' ')

But I am geeting the xml as follows:

        <copyFiles>
               <copy1>
                    <Sourcepath>D:\path1\program</Sourcepath>
                    <DestPath>c:\program</DestPath>
                </copy1>

                 <copy2>
                    <Sourcepath>D:\path2\program</Sourcepath>
                    <DestPath>c:\program</DestPath>
                  </copy2>

         <copyFiles>

The contents of my list should be as follows: ["copy1", "D:\path1\program Files", "c:\program Files\path1", "copy2", "D:\path2\program Files]", "c:\program Files\path2"]

Please help

MaxPowers
  • 5,235
  • 2
  • 44
  • 69
mystack
  • 4,910
  • 10
  • 44
  • 75

7 Answers7

1

It's hard to tell what exactly you want, but it looks like you want to split the string as follows:

a = 'this "is a string" with "4 elements"'
split = magic_splitter(a)  #How to write magic splitter?
print split  #['this', 'is a string', 'with', '4 elements']

If that's the case, what you want is to use the fantastic function shlex.split

print shlex.split(a) #['this', 'is a string', 'with', '4 elements']
mgilson
  • 300,191
  • 65
  • 633
  • 696
0

What's the output you want? You can use join to put it in whatever format you want. For example, to simply remove the spaces, use

Copyparamlist=''.join(command.split(' '))

Or if you want to replace them with %20, use

Copyparamlit='%20'.join(command.split(' '))
Rob Volgman
  • 2,104
  • 3
  • 18
  • 28
  • i can't use Copyparamlist=''.join(command.split(' ')) because it will join all the string and same is the case with Copyparamlit='%20'.join(command.split(' ')) The contents of my list should be as follows [copy1,D:\path1\program Files,c:\program Files\path1,copy2,D:\path2\program Files],c:\program Files\path2] – mystack Jul 26 '12 at 15:07
0

You need to have another separator other than space ... for example ... you can use for example the quote a separator using something as

CopyParam = command.split('"')

And should I understand the format of string command as copyName "Source" "Destination" ... You can loop on the list of triplets ... like

for i in xrange(0, len(CopyParam), 3): 
    copyname, sourcepath, destpath = CopyParam[i], CopyParam[i + 1], CopyParam[i + 2]
    # Do the code to transfer it to XML here ..

You might need to remove the empty elements from the list first ..

Mahmoud Aladdin
  • 536
  • 1
  • 3
  • 13
0

I'm assuming your command string is actually specified as;

command='copy1 "something with spaces" "somewhere else" copy2 "this thing" "elsewhere"'

if your commands are always copy commands, maybe look at splitting on the word 'copy' and working with the resulting list,

command.split('copy')
['','1 "something with spaces" "somewhere else" ','2 "this thing" "elsewhere"']
Matt Warren
  • 669
  • 8
  • 18
0

I think this thread might have what you're looking for. You're probably going to have to use regular expressions if you're trying to ignore splits that are in quotes.

How to split but ignore separators in quoted strings, in python?

Try this code:

import re
PATTERN = re.compile(r'''((?:[^ "']|"[^"]*"|'[^']*')+)''')
command = PATTERN.split(command)
Community
  • 1
  • 1
Rob Volgman
  • 2,104
  • 3
  • 18
  • 28
0

With this, it can be easily managed as a dictionary:

import shlex
split = shlex.split(commandlist)
commands = dict(zip(split[::3], zip(split[1::3], split[2::3])))

Explanation: Given the string 'copyname "source" "dest" copyname2 "source2" "dest2"'...

split = shlex.split() will split the string in the format ['copyname', 'source', 'dest', 'copyname2', 'source2','dest2']

split[::3] is doing something called splicing. This implicitly says 'Starting at the 0 index, give me every third item. split[::3] will equal ['copyname', 'copyname2']. The splicing doesn't stop there, though. split[1::3] says to start at index 1 and then give every third element after that. It will return all of the sources.

The zip function is a unique one. Given lists l1=['a','b','c'] and l2=[1,2,3], zip(l1,l2) will equal [('a',1),('b',2), ('c',3)].

zip(split[1::3], split[2::3]) will equal [('source', 'dest'), ('source2', 'dest2')].

zip(split[::3], zip(split[1::3], split[2::3])) will equal [('copyname',('source','dest')), ('copyname2',('source2','dest2'))].

The dict function will then convert each key/value pair (copyname and ('source','dest')) in the given list into a dictionary.

The commands variable is now in the format {'copyname': ('source', 'dest'), ...} To write to the xml, simply iterate through the dictionary.

Pro Tip: When iterating through a dictionary with for, each item will be a key.

And if you want, you can just use for copyname, source, dest in zip(split[::3], split[1::3], split[2::3]).

Alyssa Haroldsen
  • 3,652
  • 1
  • 20
  • 35
0

Try the following sample:

import shlex
import xml.etree.ElementTree as etree

def my_parser(s):
    command = []
    for item in shlex.split(s):
        if item.startswith('copy'):
            if command:            # any previous command was collected?
                yield command      # output one parsed command
            command = [ item ]     # start collecting new command
        else:
            command.append(item)   # collect another argument    

    if command:                    # if anything was collected
        yield command              # output the last parsed command


cmd = r'copy1 "D:\path1\program Files" "c:\program Files\path1" copy2 "D:\path2\program Files" "c:\program Files\path2"'

# Just to show what are the parsed command in the lists
for command in my_parser(cmd):
    print command

# Alternatively, constructing the XML.
e = etree.Element('copyFiles')    # root element
tree = etree.ElementTree(e)
root = tree.getroot()             # now the same as e 

for command in my_parser(cmd):
    assert len(command) == 3
    assert command[0].startswith('copy')

    e = etree.Element(command[0])  # the command name becomes the tag name 

    src = etree.Element('Sourcepath')  # subelement
    src.text = command[1]

    dst =  etree.Element('DestPath')   # subelement
    dst.text = command[2]

    e.append(src)                  # subelement appended to its parent
    e.append(dst)                  # subelement appended to its parent

    root.append(e)                 # command appended to the root element

tree.write('output.xml')

It prints:

['copy1', 'D:\\path1\\program Files', 'c:\\program Files\\path1']
['copy2', 'D:\\path2\\program Files', 'c:\\program Files\\path2']

and it produces output.xml with the following content (as one line, wrapped manually here):

<copyFiles><copy1><Sourcepath>D:\path1\program Files</Sourcepath>
<DestPath>c:\program Files\path1</DestPath></copy1>
<copy2><Sourcepath>D:\path2\program Files</Sourcepath>
<DestPath>c:\program Files\path2</DestPath></copy2></copyFiles>
pepr
  • 20,112
  • 15
  • 76
  • 139