3

I would like to parse only headers name in main.c:

#include "foo.h"
#include "bar.h"
#include <stdio.h>

int add(int a,int b){ return a+b; }
int sub(int a, int b){ return a-b; }

int main(){
    printf("%i\n",add(1,2));
}

So my perl script looks like this:

#!/usr/bin/perl 
open MAIN, $ARGV[0];

@ar = map { /#include "([^"]+)"/ ? $1 : next } <MAIN>;

#this one works (next inside for-loop, not map-loop)
for(<MAIN>){
    if(/#include "([^"]+)"/){
        push @ar2, $1;
    } else {
        next;
    }
}

print "@ar\n";
print "@ar2\n";

gives error:

Can't "next" outside a loop block 

so is next possible in map? if so, how to fix my case?

Timur Shtatland
  • 12,024
  • 2
  • 30
  • 47
milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • See also [Generate list with conditional items](https://stackoverflow.com/q/27821728/2173773) – Håkon Hægland Aug 02 '20 at 21:33
  • 2
    Tip: ALWAYS use `use strict; use warnings;`. There are other things that can be improved, but that one is crucial. – ikegami Aug 02 '20 at 22:29
  • There are no more operations after your `next` in the `for` loop, so you do not actually need the `else` block at all there. – simbabque Aug 03 '20 at 07:51

1 Answers1

8

A given iteration of map can return any number of scalars including zero.

my @ar = map { /#include "([^"]+)"/ ? $1 : () } <MAIN>;

A match with captures in list context returns the captured text on a match, and nothing on a failed match. As such, the above can be simplified.

my @ar = map { /#include "([^"]+)"/ } <MAIN>;
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • what if there will more captures in the `//`? Will the result return $1 or $2 ? – milanHrabos Aug 02 '20 at 21:46
  • Both. You can always use the conditional operator for more control. For example, `/^(.)\1(.)\2(.)\3\z/ ? ( $1, $3 ) : ()` – ikegami Aug 02 '20 at 22:07
  • but I cannot work with the `$1` then: if I use `@main_hed=map{/#include "([^"]+)"/ and abs_path($1)}
    ;`, then the `$1` will remain for even failed ones. I have to use `for` instead of `map`
    – milanHrabos Aug 02 '20 at 22:17
  • 3
    `/#include "([^"]+)"/ ? abs_path($1) : ()` – ikegami Aug 02 '20 at 22:24
  • 4
    You could also chain `map`s. `map { abs_path($_) } map { /#include "([^"]+)"/ }` – ikegami Aug 02 '20 at 22:31