473,503 Members | 1,722 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

stripping unwanted chars from string

I'm looking for the "best" way to strip a large set of chars from a filename
string (my definition of best usually means succinct and readable). I
only want to allow alphanumeric chars, dashes, and periods. This is what I
would write in Perl (bless me father, for I have sinned...):

$filename =~ tr/\w.-//cd, or equivalently
$filename =~ s/[^\w.-]//

I could just use re.sub like the second example, but that's a bit overkill.
I'm trying to figure out if there's a good way to do the same thing with
string methods. string.translate seems to do what I want, the problem is
specifying the set of chars to remove. Obviously hardcoding them all is a
non-starter.

Working with chars seems to be a bit of a pain. There's no equivalent of
the range function, one has to do something like this:
[chr(x) for x in range(ord('a'), ord('z')+1)] ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

Do that twice for letters, once for numbers, add in a few others, and I get
the chars I want to keep. Then I'd invert the set and call translate.
It's a mess and not worth the trouble. Unless there's some way to expand a
compact representation of a char list and obtain its complement, it looks
like I'll have to use a regex.

Ideally, there would be a mythical charset module that works like this:
keep = charset.expand (r'\w.-') # or r'a-zA-Z0-9_.-'
toss = charset.invert (keep)


Sadly I can find no such beast. Anyone have any insight? As of now,
regexes look like the best solution.

May 4 '06 #1
7 2272
On 4/05/2006 1:36 PM, Edward Elliott wrote:
I'm looking for the "best" way to strip a large set of chars from a filename
string (my definition of best usually means succinct and readable). I
only want to allow alphanumeric chars, dashes, and periods. This is what I
would write in **** (bless me father, for I have sinned...):
[expletives deleted] and it was wrong anyway (according to your
requirements);
using \w would keep '_' which is *NOT* alphanumeric.
I could just use re.sub like the second example, but that's a bit overkill.
I'm trying to figure out if there's a good way to do the same thing with
string methods. string.translate seems to do what I want, the problem is
specifying the set of chars to remove. Obviously hardcoding them all is a
non-starter.

Working with chars seems to be a bit of a pain. There's no equivalent of
the range function, one has to do something like this:
[chr(x) for x in range(ord('a'), ord('z')+1)] ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
alphabet = 'qwertyuiopasdfghjklzxcvbnm' # Look, Ma, no thought required!! Monkey see, monkey type. keepchars = set(alphabet + alphabet.upper() + '1234567890-.')
fixer = lambda x: ''.join(c for c in x if c in keepchars)
fixer('qwe!@#456.--Howzat?') 'qwe456.--Howzat'
Do that twice for letters, once for numbers, add in a few others, and I get
the chars I want to keep. Then I'd invert the set and call translate.
It's a mess and not worth the trouble. Unless there's some way to expand a
compact representation of a char list and obtain its complement, it looks
like I'll have to use a regex.

Ideally, there would be a mythical charset module that works like this:
keep = charset.expand (r'\w.-') # or r'a-zA-Z0-9_.-'


Where'd that '_' come from?
toss = charset.invert (keep)


Sadly I can find no such beast. Anyone have any insight? As of now,
regexes look like the best solution.


I'll leave it to somebody else to dredge up the standard riposte to your
last sentence :-)

One point on your requirements: replacing unwanted characters instead of
deleting them may be better -- theoretically possible problems with
deleting are: (1) duplicates (foo and foo_ become the same) (2) '_'
becomes '' which is not a valid filename. And a legibility problem: if
you hate '_' and ' ' so much, why not change them to '-'?

Oh and just in case the fix was accidentally applied to a path:

keepchars.update(os.sep)
if os.altsep: keepchars.update(os.altsep)

HTH,
John
May 4 '06 #2
John Machin wrote:
[expletives deleted] and it was wrong anyway (according to your
requirements);
using \w would keep '_' which is *NOT* alphanumeric.
Actually the perl is correct, the explanation was the faulty part. When in
doubt, trust the code. Plus I explicitly allowed _ further down, so the
mistake should have been fairly obvious.

>>> alphabet = 'qwertyuiopasdfghjklzxcvbnm' # Look, Ma, no thought required!! Monkey see, monkey type.


I won't dignify that with a response. The code that is, I could give a toss
about the comments. If you enjoy using such verbose, error-prone
representations in your code, god help anyone maintaining it. Including
you six months later. Quick, find the difference between these sets at a
glance:

'qwertyuiopasdfghjklzxcvbnm'
'abcdefghijklmnopqrstuvwxyz'
'abcdefghijklmnopprstuvwxyz'
'abcdefghijk1mnopqrstuvwxyz'
'qwertyuopasdfghjklzxcvbnm' # no fair peeking

And I won't even bring up locales.

>>> keepchars = set(alphabet + alphabet.upper() + '1234567890-.')
>>> fixer = lambda x: ''.join(c for c in x if c in keepchars)

Those darn monkeys, always think they're so clever! ;)
if "you can" == "you should": do(it)
else: do(not)

Sadly I can find no such beast. Anyone have any insight? As of now,
regexes look like the best solution.


I'll leave it to somebody else to dredge up the standard riposte to your
last sentence :-)


If the monstrosity above is the best you've got, regexes are clearly the
better solution. Readable trumps inscrutable any day.

One point on your requirements: replacing unwanted characters instead of
deleting them may be better -- theoretically possible problems with
deleting are: (1) duplicates (foo and foo_ become the same) (2) '_'
becomes '' which is not a valid filename.
Which is why I perform checks for emptiness and uniqueness after the strip.
I decided long ago that stripping is preferable to replacement here.

And a legibility problem: if
you hate '_' and ' ' so much, why not change them to '-'?
_ is allowed. And I do prefer -, but not for legibility. It doesn't
require me to hit Shift.

Oh and just in case the fix was accidentally applied to a path:

keepchars.update(os.sep)
if os.altsep: keepchars.update(os.altsep)


Nope, like I said this is strictly a filename. Stripping out path
components is the first thing I do. But thanks for pointing out these
common pitfalls for members of our studio audience. Tell him what he's
won, Johnny! ;)

May 4 '06 #3
>>> keepchars = set(alphabet + alphabet.upper() + '1234567890-.')
or
keepchars = set(string.letters + string.digits + '-.')


bryan

May 4 '06 #4
Bryan wrote:
>>> keepchars = set(string.letters + string.digits + '-.')


Now that looks a lot better. Just don't forget the underscore. :)

May 4 '06 #5
Edward Elliott wrote:
Bryan wrote:
>>> keepchars = set(string.letters + string.digits + '-.')

Now that looks a lot better. Just don't forget the underscore. :)

You may also want to have a look at string.translate() and
string.maketrans()

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
May 4 '06 #6
On 4/05/2006 4:30 PM, Edward Elliott wrote:
Bryan wrote:
>>> keepchars = set(string.letters + string.digits + '-.')
Now that looks a lot better. Just don't forget the underscore. :)


*Looks* better than the monkey business. Perhaps I should point out to
those of the studio audience who are huddled in an ASCII bunker (if any)
that string.letters provides the characters considered to be alphabetic
in whatever the locale is currently set to. There is no guarantee that
the operating system won't permit filenames containing other characters,
ones that the file's creator would quite reasonably consider to be
alphabetic. And of course there are languages that have characters that
one would not want to strip but can scarcely be described as alphanumeric.
import os
os.listdir(u'.') [u'\xc9t\xe9_et_hiver.doc', u'\u041c\u043e\u0441\u043a\u0432\u0430.txt',
u'\u5f20\u654f.txt']
import string
string.letters

'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW XYZ'

Doing
import locale; locale.setlocale(locale.LC_ALL, '')
would make string.letters work (for me) with the first file above, but
that's all.
May 4 '06 #7
Edward Elliott <no****@127.0.0.1> wrote:
I'm looking for the "best" way to strip a large set of chars from a filename
string (my definition of best usually means succinct and readable). I
only want to allow alphanumeric chars, dashes, and periods. This is what I
would write in Perl (bless me father, for I have sinned...):

$filename =~ tr/\w.-//cd, or equivalently
$filename =~ s/[^\w.-]//

I could just use re.sub like the second example, but that's a bit overkill.
I'm trying to figure out if there's a good way to do the same thing with
string methods. string.translate seems to do what I want, the problem is
specifying the set of chars to remove. Obviously hardcoding them all is a
non-starter.


(untested code, but, the general idea shd be correct)...:

class KeepOnly(object):
allchars = ''.join(chr(i) for i in xrange(256))
identity = string.maketrans('', '')

def __init__(self, chars_to_keep):
self.chars_to_delete = self.allchars.translate(
self.identity, chars_to_keep)

def __call__(self, some_string):
return some_string.translate(self.identity,
self.chars_to_delete)
Alex
May 4 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3309
by: joram gemma | last post by:
Hello, on windows python 2.4.1 I have the following problem >>> s = 'D:\\music\\D\\Daniel Lanois\\For the beauty of Wynona' >>> print s D:\music\D\Daniel Lanois\For the beauty of Wynona >>>...
1
9960
by: JuniorLinn | last post by:
Hi there - I would like to share this strip of code with our SQL 2000 DBA community. The code below strips all non-numeric characters from a given string field and rebuilds the string. Very...
15
5994
by: Jeff North | last post by:
Hi, I'm using a control called HTMLArea which allows a person to enter text and converts the format instructions to html tags. Most of my users know nothing about html so this is perfect for my...
16
2769
by: lovecreatesbeauty | last post by:
/* When should we worry about the unwanted chars in input stream? Can we predicate this kind of behavior and prevent it before debugging and testing? What's the guideline for dealing with it? ...
3
2565
by: et | last post by:
How can I strip out unwanted characters in a string before updating the database? For instance, in names & addresses in our client table, we want only letters and numbers, no punctuation. Is...
7
1502
by: orangeDinosaur | last post by:
Hello, I am encountering a behavior I can think of reason for. Sometimes, when I use the .strip module for strings, it takes away more than what I've specified. For example: >>> a = ' ...
6
2657
by: eight02645999 | last post by:
hi wish to ask a qns on strip i wish to strip all spaces in front of a line (in text file) f = open("textfile","rU") while (1): line = f.readline().strip() if line == '': break print line
3
2407
by: Jason | last post by:
First things first, let me say that I couldn't decide whether to post this to the PHP ng, or to an XML ng. I know from experience that you guys know what you're talking about, though, and all of...
4
1399
by: Tim Cook | last post by:
Hi All, I just ran into an issue with the rstrip method when using it on path strings. When executing a function I have a need to strip off a portion of the current working directory and add...
0
7086
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7332
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6991
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5578
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5014
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3167
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
1512
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
736
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
382
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.