0

I've been following the guidance here: Extract Substring Using RegExp in Plain Bash

I can't seem to get my code to work properly:

This echoes correctly:

for filename in ./unsent_xmls/*.xml; do
    echo $filename |  perl -lne 'print $& if /(\d{4})(?=-)/'
done

but when I try this it prints an empty result:

for filename in ./unsent_xmls/*.xml; do
    package=$filename |  perl -lne 'print $& if /(\d{4})(?=-)/'
    echo $package
done

I've tried a number of different iterations.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
GeneralBear
  • 1,011
  • 3
  • 11
  • 35
  • 1
    Refresh my memory; what's the `perl` command supposed to do? There's almost certainly a simpler way to do this in `bash` alone. – chepner Apr 30 '18 at 15:49
  • Or `perl` alone :). But that perl matches the RE. If it matches, it prints "The string matched by the last successful pattern match". (Which is what `$&` means) – Sobrique May 01 '18 at 09:55

2 Answers2

3

There are two problems.

  1. package=$filename produces no output to be piped to perl
  2. package is only set in the subshell that runs the left-hand side of the pipeline; it's not set after the pipeline completes.

If all you want are the 4 digits preceding the first - in the file name, use

for filename in ./unset_xmls/*.xml; do
    [[ $filename =~ ([[:digit:]]{4})- ]] && package=${BASH_REMATCH[1]}
    echo "$package"
done
chepner
  • 497,756
  • 71
  • 530
  • 681
1

Three things: you still need the echo in the pipeline, you need $( ) to capture the output from the pipeline so you can assign it to a variable, and you should use double-quotes around variable references (to prevent possible parsing oddities):

for filename in ./unsent_xmls/*.xml; do
    package=$(echo "$filename" |  perl -lne 'print $& if /(\d{4})(?=-)/')
    echo "$package"
done
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151