in reply to Re: Setting a Variable from filename
in thread Setting a Variable from filename

Apologies, my current code is in work, however your response nails it for me I think, I hadn't considered using grep into a 2nd array where I then know the index will be [0].

Thanks for the response.

Replies are listed 'Best First'.
Re^3: Setting a Variable from filename
by haukex (Archbishop) on Apr 29, 2018 at 22:00 UTC

    As always, There Is More Than One Way To Do It. If you're certain that the grep condition will always match exactly one element of @files:

    • $ScontrolFile = (grep {/_CF_/} @files)[0]; - create a "temporary" list and get its first element
    • ($ScontrolFile) = grep {/_CF_/} @files; - use assignment in list context
    • use List::Util qw/first/; $ScontrolFile = first {/_CF_/} @files; - use first from the core module List::Util, which has the advantage that it stops looking once it finds a match

    However, none of the above solutions provide protection against the case that @files does not contain exactly one string matching the pattern, which is why I suggested the extra array. <update> AnomalousMonk showed a way to add the check to the second of my examples above. To add a check to the other two, </update> you could theoretically search the array a second time, using grep in scalar context (if ( grep({/_CF_/} @files)!=1 ) { die ... }), but that's fairly wasteful and you'll have duplicated code (the grep block). Of course, you can also write an explicit loop:

    my $ScontrolFile; for my $file (@files) { if ( $file =~ /_CF_/ ) { die "more than one _CF_ file found in: @files" if defined $ScontrolFile; $ScontrolFile = $file; } } die "_CF_ file not found in: @files" unless defined $ScontrolFile;

    Update: Added check for >1 file in the above code, and see update in text.

Re^3: Setting a Variable from filename
by Laurent_R (Canon) on Apr 29, 2018 at 17:43 UTC
    Well, you could grep your values into the same array if you wished:
    @files = grep { /_CF_/ } @files;
    Now, @files will contain only the file(s) matching the regex.

    But it is probably clearer (and easier to debug if you need) to grep the matching values into a new array and leave the original one untouched.

Re^3: Setting a Variable from filename (updated)
by AnomalousMonk (Archbishop) on Apr 30, 2018 at 03:06 UTC

    Yet Another Way to capture first matching file, if any, and number of matching files concisely:

    c:\@Work\Perl\monks>perl -wMstrict -le "my @files = qw(xxx 1st_CF_xx CF__ 2nd_CF_yy CF); ;; my $n_CF_ = my ($first_CF_) = grep /_CF_/, @files; ;; print qq{number of _CF_ files: $n_CF_}; if ($n_CF_ == 1) { print qq{just one: '$first_CF_'}; } " number of _CF_ files: 2 c:\@Work\Perl\monks>perl -wMstrict -le "my @files = qw(xxx 1st_CF_xx CF__ CF); ;; my $n_CF_ = my ($first_CF_) = grep /_CF_/, @files; ;; print qq{number of _CF_ files: $n_CF_}; if ($n_CF_ == 1) { print qq{just one: '$first_CF_'}; } " number of _CF_ files: 1 just one: '1st_CF_xx' c:\@Work\Perl\monks>perl -wMstrict -le "my @files = qw(xxx yyy zzz); ;; my $n_CF_ = my ($first_CF_) = grep /_CF_/, @files; ;; print qq{number of _CF_ files: $n_CF_}; if ($n_CF_ == 1) { print qq{just one: '$first_CF_'}; } " number of _CF_ files: 0

    Update: Be aware that if no files match the grep condition in the example code above,  $first_CF_ is undefined.


    Give a man a fish:  <%-{-{-{-<