I’m new to the map and grep functions and I’m trying to make an existing script more concise.
I can “grep” the @tracknames successfully but I’m having a problem with “map”. I want @trackartist to return true if two consecutive “–” are found in a line and take the value of $1, otherwise false, but it returns the whole line if the upper condition is not met.
What am I doing wrong?
my @tracknames = grep /^\d\d\..*?(\.(?:flac|wv))$/, <*.*>;
my @trackartist = map { s/^\d\d\.\s(.*?)\s--.*?\.(?:flac|wv)$/$1/; $_; } <*.*>;
Sample of files
01. some track artist 1 -- some track name 1.(flac or wv)
02. some track artist 2 -- some track name 2.(flac or wv)
03. some track artist 3 -- some track name 3.(flac or wv)
etc.
Remember that
grepis for filtering a list andmapis for transforming a list. Right now, yourmapstatement returns$_for every item in the list. If$_matches the pattern in your substitution, it will be modified and replaced with the first match. Otherwise, it’s not modified and the original$_is returned.It sounds like you want to filter out items that don’t match the pattern. One way would be to combine a map and a grep:
Of course, this means you’re doing the same pattern match twice. Another approach is to do a transform with
map, but transform anything that doesn’t match the pattern into an empty list.This uses the ternary conditional operator (
?:) to check if the regex matches (returning a true value). If it does,$1is returned from themapblock, if not, an empty list( )is returned, which adds nothing to the list resulting from themap.As a side note, you might want to look into using the glob function rather than
<>, which has some disadvantages.