Forcing list context

Discussion in 'Perl Misc' started by Brian Greenfield, Dec 31, 2003.

  1. I was writing a script that needed to find the free space on a mounted
    Linux partition (mounted on /backup) and I wrote the following
    snippet:

    my @res = split /\s+/, grep m{/backup}, `df`; # 1

    The problem being that the second argument of split is evaluated in
    scalar context so grep returns the number of matches instead of the
    actual match (there will only ever be a single match). I got round
    this problem by inserting a join so that grep is evaluated in list
    context:

    my @res = split /\s+/, join '', (grep m{/backup}, `df`); # 2

    While this works, it seems a little kludgey. I know I could have
    indexed grep's list result:

    my @res = split /\s+/, (grep m{/backup}, `df`)[0]; # 3

    I intended to go on to do a list splice to get the fields I wanted
    (the second to fourth) and I wanted to avoid the using indexing twice:

    my @res = (split /\s+/, (grep m{/backup}, `df`)[0])[1..3]; # 4

    I ended up using the splice with method 2:

    my @res = (split /\s+/,
    join '', (grep m{/backup}, `df`))[1..3]; # 5

    Does Perl offer any other ways of forcing list context?

    Sample output from df, for reference

    Filesystem 1K-blocks Used Available Use% Mounted on
    /dev/hdb2 29300456 20002976 7809060 72% /backups
    /dev/hdc1 12998064 3069480 9268316 25% /mirrors
     
    Brian Greenfield, Dec 31, 2003
    #1
    1. Advertising

  2. On Wed, 31 Dec 2003 12:02:27 GMT
    Brian Greenfield <> wrote:

    > I was writing a script that needed to find the free space on a
    > mounted Linux partition

    <snip>
    > Does Perl offer any other ways of forcing list context?
    >
    > Sample output from df, for reference
    >
    > Filesystem 1K-blocks Used Available Use% Mounted on
    > /dev/hdb2 29300456 20002976 7809060 72% /backups
    > /dev/hdc1 12998064 3069480 9268316 25% /mirrors


    A simple one liner that gets what you want is ...

    host> df | perl -ne 'if(/home/){@line = split;print $line[3],"\n";}'

    My though is it's easier to use a regex to get what you want versus
    using 'grep' in the context of what you're trying to do. However,
    that's my opinion :)

    However, you may want to look over the Filesys::DiskFree module. It
    may make your tasks easier :)


    --
    Jim

    Copyright notice: all code written by the author in this post is
    released under the GPL. http://www.gnu.org/licenses/gpl.txt
    for more information.

    a fortune quote ...
    A little inaccuracy sometimes saves tons of explanation. -- H.
    H. Munroe
     
    James Willmore, Dec 31, 2003
    #2
    1. Advertising

  3. Brian Greenfield

    l v Guest

    James Willmore wrote:
    > On Wed, 31 Dec 2003 12:02:27 GMT
    > Brian Greenfield <> wrote:
    >
    >
    >>I was writing a script that needed to find the free space on a
    >>mounted Linux partition

    >
    > <snip>
    >
    >>Does Perl offer any other ways of forcing list context?
    >>
    >>Sample output from df, for reference
    >>
    >>Filesystem 1K-blocks Used Available Use% Mounted on
    >>/dev/hdb2 29300456 20002976 7809060 72% /backups
    >>/dev/hdc1 12998064 3069480 9268316 25% /mirrors

    >
    >
    > A simple one liner that gets what you want is ...
    >
    > host> df | perl -ne 'if(/home/){@line = split;print $line[3],"\n";}'
    >
    > My though is it's easier to use a regex to get what you want versus
    > using 'grep' in the context of what you're trying to do. However,
    > that's my opinion :)
    >
    > However, you may want to look over the Filesys::DiskFree module. It
    > may make your tasks easier :)
    >
    >


    using the perl option -a will auto-split $_ into @F, therefore

    df | perl -nae 'print "$F[3]\n" if(/home/)'

    Len
     
    l v, Dec 31, 2003
    #3
  4. Brian Greenfield

    l v Guest

    Brian Greenfield wrote:

    > I was writing a script that needed to find the free space on a mounted
    > Linux partition (mounted on /backup) and I wrote the following
    > snippet:
    >
    > my @res = split /\s+/, grep m{/backup}, `df`; # 1
    >
    > The problem being that the second argument of split is evaluated in
    > scalar context so grep returns the number of matches instead of the
    > actual match (there will only ever be a single match). I got round
    > this problem by inserting a join so that grep is evaluated in list
    > context:
    >
    > my @res = split /\s+/, join '', (grep m{/backup}, `df`); # 2
    >
    > While this works, it seems a little kludgey. I know I could have
    > indexed grep's list result:
    >
    > my @res = split /\s+/, (grep m{/backup}, `df`)[0]; # 3
    >
    > I intended to go on to do a list splice to get the fields I wanted
    > (the second to fourth) and I wanted to avoid the using indexing twice:
    >
    > my @res = (split /\s+/, (grep m{/backup}, `df`)[0])[1..3]; # 4
    >
    > I ended up using the splice with method 2:
    >
    > my @res = (split /\s+/,
    > join '', (grep m{/backup}, `df`))[1..3]; # 5
    >
    > Does Perl offer any other ways of forcing list context?
    >
    > Sample output from df, for reference
    >
    > Filesystem 1K-blocks Used Available Use% Mounted on
    > /dev/hdb2 29300456 20002976 7809060 72% /backups
    > /dev/hdc1 12998064 3069480 9268316 25% /mirrors
    >


    I think you are attempting to do too much in one line. However @{[ ]}
    can be used to force list context. Split is looking for a scalar and
    you are feeding it an array of 1. Try the following:

    #!/usr/bin/perl

    my @result = grep m{/backups}, `df`;
    mmy @res = split (/\s+/, $result[0]);

    for my $r (@res) {
    print "r = $r\n";
    }


    I would personally add the file system to the df command to lighten
    greps load, if you have alot of mount points. df /backups will return
    for /backups only, including the header.
    my @result = grep m{/backups}, `df /backups`;

    my $.02
    Len
     
    l v, Jan 1, 2004
    #4
  5. In message <>, Brian
    Greenfield <> writes
    >I ended up using the splice with method 2:
    >
    > my @res = (split /\s+/,
    > join '', (grep m{/backup}, `df`))[1..3]; # 5
    >
    >Does Perl offer any other ways of forcing list context?


    Absolutely not the answer to the question that you asked, but a neat-ish
    (untested) solution is:

    my $res = `df | awk '/backups/ {print $4}'`

    Regards,
    --
    Bruce Horrocks
    Surrey
    England
    <firstname>@<surname>.plus.com -- fix the obvious for email
     
    Bruce Horrocks, Jan 1, 2004
    #5
  6. In article <>,
    Brian Greenfield <> wrote:

    >I was writing a script that needed to find the free space on a mounted
    >Linux partition (mounted on /backup)...


    Just a thought, but on Linux, rather than forking df, you can read all
    information on current mount points from /proc/self/mounts. This returns
    one line per mount point, containing the following space-separated items:

    device mountpoint filesystem flags fsck1 fsck2
     
    Lawrence D'Oliveiro, Jan 1, 2004
    #6
  7. Brian Greenfield wrote:
    >
    > I was writing a script that needed to find the free space on a mounted
    > Linux partition (mounted on /backup) and I wrote the following
    > snippet:
    >
    > my @res = split /\s+/, grep m{/backup}, `df`; # 1
    >
    > The problem being that the second argument of split is evaluated in
    > scalar context so grep returns the number of matches instead of the
    > actual match (there will only ever be a single match). I got round
    > this problem by inserting a join so that grep is evaluated in list
    > context:
    >
    > my @res = split /\s+/, join '', (grep m{/backup}, `df`); # 2
    >
    > While this works, it seems a little kludgey. I know I could have
    > indexed grep's list result:
    >
    > my @res = split /\s+/, (grep m{/backup}, `df`)[0]; # 3
    >
    > I intended to go on to do a list splice to get the fields I wanted
    > (the second to fourth) and I wanted to avoid the using indexing twice:
    >
    > my @res = (split /\s+/, (grep m{/backup}, `df`)[0])[1..3]; # 4
    >
    > I ended up using the splice with method 2:
    >
    > my @res = (split /\s+/,
    > join '', (grep m{/backup}, `df`))[1..3]; # 5
    >
    > Does Perl offer any other ways of forcing list context?
    >
    > Sample output from df, for reference
    >
    > Filesystem 1K-blocks Used Available Use% Mounted on
    > /dev/hdb2 29300456 20002976 7809060 72% /backups
    > /dev/hdc1 12998064 3069480 9268316 25% /mirrors


    I would do it this way:

    my @res = `df /backup` =~ /(?<=\s)\d+(?=\s)/g;



    John
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Jan 1, 2004
    #7
  8. On Wed, 31 Dec 2003 18:28:12 -0600, l v <> wrote:

    >Brian Greenfield wrote:
    >
    >> my @res = (split /\s+/,
    >> join '', (grep m{/backup}, `df`))[1..3]; # 5

    >
    >I think you are attempting to do too much in one line.


    I know. It just sorta grew:)

    >However @{[ ]}
    >can be used to force list context.


    Which is what I was looking for, thanks. (Even though I wan't be using
    it - I much prefer John W. Krahn method's oven my own.)
     
    Brian Greenfield, Jan 1, 2004
    #8
  9. On Thu, 01 Jan 2004 11:46:09 GMT, "John W. Krahn" <>
    wrote:

    >Brian Greenfield wrote:
    >>
    >> my @res = (split /\s+/,
    >> join '', (grep m{/backup}, `df`))[1..3]; # 5

    >
    >I would do it this way:
    >
    >my @res = `df /backup` =~ /(?<=\s)\d+(?=\s)/g;


    That's much cleaner than my overly-complicated method. Thanks John.
    (And thanks for pointing out 'df /backups' - I never thought to look
    first at arguments to df.
     
    Brian Greenfield, Jan 1, 2004
    #9
  10. On Wed, 31 Dec 2003 12:02:27 GMT,
    Brian Greenfield <> wrote:
    > I was writing a script that needed to find the free space on a mounted
    > Linux partition (mounted on /backup) and I wrote the following
    > snippet:


    [snip]

    Apart from all the other suggestions you've had about parsing df output
    (and mind that it can get quite complicated to do that reliably), and to
    read the /proc file system directly, there is the Filesys::Df module,
    available from CPAN, which is a wrapper wround Filesys::Statvfs, which
    is a wrapper around your system's statvfs call.

    Using that will probably make your program more portable (to all
    environments where statvfs is available, which includes linux, and all
    major unices I know of), give you more information when needed, and most
    likely is a lot faster and lighter on the machine as well.

    Apart from that, there are also Filesys::DiskFree (runs external df
    command), and Filesys::DiskSpace (calls statvfs), neither of which I've
    tried.

    Martien
    --
    |
    Martien Verbruggen | Little girls, like butterflies, need no
    | excuse - Lazarus Long
    |
     
    Martien Verbruggen, Jan 1, 2004
    #10
  11. On Wed, 31 Dec 2003 13:43:19 GMT, James Willmore
    <> wrote:

    >A simple one liner that gets what you want is ...
    >
    >host> df | perl -ne 'if(/home/){@line = split;print $line[3],"\n";}'


    df | perl -lne '/home/ and print +(split)[3]'

    or

    df | perl -lne 'print +(split)[3] if /home/'

    [Just to pinpoint that it is not necessary to create an intermediate
    variable...]


    Michele
    --
    # This prints: Just another Perl hacker,
    seek DATA,15,0 and print q... <DATA>;
    __END__
     
    Michele Dondi, Jan 3, 2004
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VS_NET_DEV
    Replies:
    2
    Views:
    3,816
    jenny
    May 25, 2004
  2. =?Utf-8?B?U3VuU21pbGU=?=
    Replies:
    0
    Views:
    713
    =?Utf-8?B?U3VuU21pbGU=?=
    Jan 10, 2006
  3. Peter Kay

    Forcing Array Context

    Peter Kay, Aug 16, 2004, in forum: Perl Misc
    Replies:
    11
    Views:
    170
    Brian McCauley
    Aug 20, 2004
  4. Bo Lindbergh

    List context versus list context

    Bo Lindbergh, Jun 21, 2006, in forum: Perl Misc
    Replies:
    12
    Views:
    234
    Charles DeRykus
    Jun 28, 2006
  5. A. Farber

    Forcing list context on <$fh>

    A. Farber, Feb 26, 2009, in forum: Perl Misc
    Replies:
    23
    Views:
    240
    Gunnar Hjalmarsson
    Mar 9, 2009
Loading...

Share This Page