chaskins has asked for the wisdom of the Perl Monks concerning the following question:
I have a string I need to split up and store each word as a new variable. I've tries using the 'split' command, but the problem here is that the white spaces vary in size. Does anyone know how I could do this? Here is an example of the string;
Pid DenyMode R/W Oplock Name
Thanks
Chris
Re: Splitting each word in a string
by busunsl (Vicar) on Jun 26, 2001 at 14:40 UTC
|
Split takes a regex as delimiter, so you can use:
my @words = split /\s+/, $string;
| [reply] [d/l] |
Re: Splitting each word in a string
by ariels (Curate) on Jun 26, 2001 at 14:43 UTC
|
| [reply] |
|
Yep, sorry I was not thinking this morning :( DOH!
Chris
| [reply] |
Re: Splitting each word in a string
by azatoth (Curate) on Jun 26, 2001 at 14:43 UTC
|
my @array = split /\s+/, $string;
Update: bah, too slow
Azatoth a.k.a Captain Whiplash
Make Your Die Messages Full of Wisdom!
Get YOUR PerlMonks Stagename here!
Want to speak like a Londoner? | [reply] [d/l] |
Re: Splitting each word in a string
by grinder (Bishop) on Jun 26, 2001 at 19:59 UTC
|
I smell the parsing of smbstatus -L, looking for file locks on Samba-mounted drives...
The use of split isn't quite enough, should you (like me)
happen to have users who create file names with spaces. You
have to do it in two parts, working forwards and backwards
to isolate the file name. I have some ugly code to do this.
Warning: ugly code ahead!
This is not at all bullet-proof, but feel free to adapt
the nuggets to do something better.
#! /usr/bin/perl -w
use strict;
open IN, '/usr/local/bin/smbstatus -L 2>/dev/null |'
or die "Cannot open input pipe from smbstatus: $!\n";
while( <IN> ) {
chomp;
last if /^-*$/;
}
while( <IN> ) {
chomp;
my( $pid, $mode, $rw, $oplock, $rest ) = split(' ', $_, 5);
my( $name, $dayname, $mon, $day, $timestamp, $year ) =
($rest =~ /(.*?)\s+(\S{3})\s+(\S{3})\s+(\d+)\s+(\d+:\d+:\d+)\s
++(\d+)$/);
last unless defined $pid;
print "[$pid] [$name]\n";
}
I hacked this up ages ago. I guess I should dust it off and make it a little cleaner. When I get a round tuit.
-- g r i n d e r
| [reply] [d/l] |
Re: Splitting each word in a string
by mrmick (Curate) on Jun 26, 2001 at 17:04 UTC
|
While this can be done, you may want to look
here,
here,
or here
to see why you may not want to do things this way.
Mick | [reply] |
Re: Splitting each word in a string
by khota (Initiate) on Jun 26, 2001 at 18:50 UTC
|
You can use
split (/ +/,$string);
The + meaning that you want to consider one or more spaces as separators.
| [reply] |
Re: Splitting each word in a string
by thatguy (Parson) on Jun 26, 2001 at 18:51 UTC
|
my @string="Pid DenyMode R/W Oplock Name";
foreach (@string) {
my ($pid,$deny,$rw,$oplock,$name) = split;
# do something here
}
yeah, it's big. | [reply] [d/l] |
Re: Splitting each word in a string
by IraTarball (Monk) on Jun 26, 2001 at 20:45 UTC
|
I know you've already figured this out but, doesn't split use \s+ by default? So...
chomp ($line = <FH>);
@vars = split $line;
Get's you the strings to use for whatever evil purposes you might have.
"So... What do all these little arrows mean?"
~unknown | [reply] [d/l] |
|
Well, yeah, split uses /\s+/
by default - sort of. However, the first argument, if any,
of split is the regular expression. Only if
the first argument is missing, it results to the default.
In your example, which of course you haven't tested, you
give split one argument. One argument split
will split $_, using the regular expression
given - in your case, the value of $line.
Which is not at all what you want.
I said "sort of", meaning that the default case (that is,
no arguments to split) trailing empty fields
are removed - just like in awk. Which doesn't
happen if you use /\s+/ as first argument.
Use ' ' to get the effect of the default
behaviour.
You know, you would have saved a lot of trouble, from both
you and me (and people who thought you spoke the truth and
used your suggestion) if you had either tried out your
suggestion or had consulted the manual page. But I guess a
quick typing without thinking is the fast lane to fame.
-- Abigail
| [reply] [d/l] [select] |
|
trailing empty fields are removed - just like in awk.
Which doesn't happen if you use /\s+/ as first argument
No, the default case is different from /\s+/ in that a
leading empty field is ignored. The only way to
get Perl to not strip trailing empty fields is to pass a
3rd argument to split, usually -1.
I won't complain about you having wasted my time by getting
this wrong. This isn't comp.lang.perl.* and most of us like
it that way. If you want to complain about people wasting
your time, then comp.lang.perl.* is probably a better forum
for you.
We're all here to have fun and there are plenty of
us to answer questions quite correctly as well as incorrectly
(and lots of shades of grey in between) and then discuss
the results. Many of us end up learning a lot of Perl in
the process, but such isn't the only purpose.
Sure, checking your answers before you post is prudent
and polite, but so is not grousing at people when they
make a mistake.
Have the appropriate amount of fun...
-
tye
(but my friends call me "Tye")
| [reply] |
|
Of course you're right about split. My fingers went faster than my brain. I didn't know about the difference between /\s+/ and ' '. In fact Programming Perl seems to indicate that these are equivalent, but checking perldoc I can see that they are not.
Saved 'a lot' of trouble? Really? Did this take that much time? As for others thinking I was authoritative, I thought my posting was phrased in a questioning way. Sometimes replies are for the edification of the replier as well. Any way, I don't know about you but I wouldn't blindly implement solutions posted by random contributors (especially lowly acolytes ;-) without running a couple of test cases first.
Well, I'll continue typing as fast as I can and maybe some day I'll get one right.
Thanks,
Ira
"So... What do all these little arrows mean?"
~unknown
| [reply] [d/l] |
|
|
|