views:

650

answers:

4

Hi Everyones,

I would like to remove one null byte in a string, and sometime replace it with another char. Like that :

string = "41 00 36 00 36 00 00 00 57 00 46 00 42 00 41 00 61 00 62 00 73 00 20 00 36 00"

i was thinking about using random and replace, but replace always start by the first one:

replace("00","B",1)

So it's not random.

Any help will be appreciated !

EDIT: i meant null by 00, and i made a mistake:

string = "41 00 36 00 36 00 00 00 57 00 46 00 42 00 41 00 61 00 62 00 73 00 20 00 36 00"

Thanks

+1  A: 

Ugly code tested in Python 3.1.1

import random
s = "a00b00c00d00e00f00g"
s1 = s.split("00")
i = random.randint(1,s.count("00"))
s2 = "00".join(s1[:i])
s3 = "00".join(s1[i:])
print (s2+"EE"+s3)
mizipzor
I started going down this path, but if the string contains `000` you'll only ever replace it with `EE0` and never `0EE` -- it's not clear if OP requires this.
ephemient
Until its made clear its required, assume its not. ;)
mizipzor
+7  A: 

Not only that, but 00 isn't "a null" by any stretch of the imagination -- it's a 2-characters string. You appear to silently assume that your string is made up of substrings each of two hex digits, and any string operation you perform will have no idea about this little private convention of yours -- if you do manage to "replace a random 00" it might well be one made up of the second digit of, say, "F0", followed by the first digit of, say, "03": not what you probably mean!

A logically cleaner approach is to first split your string into the 2-digits pieces, thus making your unspoken assumption clear and explicit instead:

>>> string = "4100360036000000570046004200410061006200730020003600"
>>> pieces = [string[i:i+2] for i in range(0, len(string), 2)]
>>> pieces
['41', '00', '36', '00', '36', '00', '00', '00', '57', '00', '46', '00', '42', '00', '41', '00', '61', '00', '62', '00', '73', '00', '20', '00', '36', '00']
>>>

Yes, this can be made much more concise, but I'm striving for clarity and conceptual sharpness here!-).

Now locate all the '00' digits:

>>> where0s = [i for i in range(len(pieces)) if pieces[i] == '00']
>>> where0s
[1, 3, 5, 6, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25]

(again, easy to make compact, but this is the clearest way;-).

Now get a random choice out of the where0s and either remove it, or replace it with, for example, 'BA', then rejoin the string:

>>> import random
>>> pickone = random.choice(where0s)
>>> pickone
25
>>> # if replacing:
... 
>>> pieces[pickone] = 'BA'
>>> ''.join(pieces)
'41003600360000005700460042004100610062007300200036BA'
>>> # if removing:
... 
>>> del pieces[pickone]
>>> ''.join(pieces)
'41003600360000005700460042004100610062007300200036'
>>>

If this is indeed the exact operation you want to perform, but you want more conciseness and speed rather than this totally-spelled-out clarity, we can of course keep developing the idea!

Alex Martelli
+1: Upon reflection, my answer simplifies to yours.
Brent Newey
A: 

This solution grabs all possible locations of "00" for even values of the string and chooses one at random. It should solve your problem:

from random import choice

string = "4100360036000000570046004200410061006200730020003600"

zeroes = []

for i, s in enumerate(string):
    if i % 2 == 0 and i < len(string) - 1 and string[i:i + 2] == "00":
        zeroes.append(i)

c = choice(zeroes)
string = string[:c] + '0B' + string[c + 2:]
print string
Brent Newey
A: 

You cannot replace bytes in a string. Instead, you want to use an array for this.

import array
s = "4100360036000000570046004200410061006200730020003600"
a = array.array('c',s)
b = array.array('c',"B") # make a one character array containing B
print a
a[6] = b[0]
print b

Of course, if you intended these to be the hex codes for characters then you would need to use the hex() and chr() functions to convert between integers and strings of hex characters.

Michael Dillon