0

I have variables where I store regular expressions and than I want to find files in local folder that match that regex

Basically, I have regex for filename and for its extensions which I want to concatenate and then use them in ereg to search for files

So, here is an example of how it looks like:

declare -r CPMOVE_REGEX="^cpmove-[a-z][a-z0-9]{0,16}"
declare -r TAR_REGEX=".tar$"

and then somewhere in the scriptI do the following.

for b in $(ls -1 | egrep "$CPMOVE_REGEX$TAR_REGEX");
do
  backups+=($b);
done
  • let's assume backups variable is declared somewhere before.

  • I understand that $CPMOVE_REGEX$TAR_REGEX is wrong, and I would like to know how to do it a right way.

Cyrus
  • 84,225
  • 14
  • 89
  • 153

3 Answers3

0

One of the ways to make it work is to put your vars in to curly brackets: "${CPMOVE_REGEX}${TAR_REGEX}"

Actually, I found it before posting this message, but I named my test files incorrectly, so they didn't match the regexp. So, that was the issue.

Thanks to Micha Wiedenmann who provided the link to the answer

  • 1
    Curly braces shouldn't matter in this case. They don't hurt, but they're only needed when you need explicit control over where the variable reference ends. That is, when the variable name is followed by something that *could* be part of the variable name but isn't (like `"${var}text"` vs `"$vartext"`) or want to use a complex expansion (like `"${var/pattern/replace}"`). See [this question](https://stackoverflow.com/questions/8748831/when-do-we-need-curly-braces-around-shell-variables) for more info. – Gordon Davisson Sep 01 '19 at 17:58
0

Your regexp's problem is not in the extension part ($TAR_REGEX) but in the first part. Try to echo the whole string $CPMOVE_REGEX$TAR_REGEX and do some testing on the command line. When the regexp is ok, then put it in the script. There are no problems combining two variables into one string, and use it as egrep parameter, like in this working example:


root@localhost ~ $ declare -r P1='^[0-9]+\-.{3}'
root@localhost ~ $ ls | egrep "$P1"
20190315-GO2.sql
root@localhost ~ $ declare -r P2='.sql$'
root@localhost ~ $ ls | egrep "$P1$P2"
20190315-GO2.sql
root@localhost ~ $

Francesco Gasparetto
  • 1,819
  • 16
  • 20
  • 2
    Please put double-quotes around those variable references! Without them, there's a possibility that the regex could be a gob-pattern-type match for one or more files, which would make a complete mess. – Gordon Davisson Sep 01 '19 at 18:00
0

how to do it a right way.

Probably something along:

declare -r CPMOVE_REGEX="cpmove-[a-z][a-z0-9]{0,16}"
declare -r TAR_REGEX=".tar"
IFS= readarray -d '' -t backups < <(find . -regextype posix-egrep -regex ".*/$CPMOVE_REGEX$TAR_REGEX" -print0)

Pre bashv4 doesn't has -d '' option with readarray. If you bash lower then v4, you need a while read loop:

while IFS= read -r tmp; do
    backups+=("$tmp")
done < <(find . -regextype posix-egrep -regex ".*/$CPMOVE_REGEX$TAR_REGEX" -print0)

But because your filenames have no whitespaces in them, which you filter with the regex, then if you are interested in filenames only without the directory paths, probably you could go with reading a newline separated list. That's only if you are sure you will never have any newlines in filenames.

IFS=$'\n' read -r -a backups < <(find . -regextype posix-egrep -regex ".*/$CPMOVE_REGEX$TAR_REGEX" -print "%f\n")

or

IFS=$'\n' backups=($(find . -regextype posix-egrep -regex ".*/$CPMOVE_REGEX$TAR_REGEX" -print "%f\n"))

Notes:

KamilCuk
  • 120,984
  • 8
  • 59
  • 111