mgig
mgig

Reputation: 2915

How can I match zero or more instances of a pattern in bash?

I'm trying to loop through a bunch of file prefixes looking for a single line matching a given pattern from each file. I have extracted and generalized a couple examples and have used them below to illustrate my question.

I searched for a line that may have some spaces at the beginning, followed by the number 1234, with maybe some more spaces, and then the number 98765. I know the file of interest begins with l76.logsheet and I want to extract the line from the file that ends with one or more numbers. However, I want to make sure I exclude files ending with anything else (of which there are too many options to reasonably use the grep --exclude option). Here's how I did it from the tcsh shell:

tcsh% grep -E '^\s{0,}1234\s+98765' l76.logsheet[0-9]{0,}
l76.logsheet10:1234   98765       y  13:02:44     2

And here's another example where I was again searching for 98765, but with a different number out front and a different file prefix:

tcsh% grep -E '^\s{0,}4321\s+98765' k43.logsheet[0-9]{0,}
k43.logsheet1:  4321    98765 y    13:06:38    14

Works great and returns just what I need.

My problem is with the bash shell. Repeating the same command returns a rather interesting result. With the first line, there are no problems:

bash$ grep -E '^\s{0,}1234\s+98765' l76.logsheet[0-9]{0,}

which returns:

l76.logsheet10:1234   98765       y  13:02:44     2

But the result for the second example only has one digit at the end of the filename. This causes bash to throw an error before providing the correct result:

bash$ grep -E '^\s{0,}4321\s+98765' k43.logsheet[0-9]{0,}
grep: k43.logsheet[0-9]0: No such file or directory
k43.logsheet1:  4321    98765 y    13:06:38    14

My question is, how do I search for files ending in zero or more of the previous pattern from the bash shell? I have a work around, but I'm looking for an actual answer to this question, which may save me (and hopefully others) time in the future.

Upvotes: 3

Views: 3690

Answers (1)

John1024
John1024

Reputation: 113834

First, make sure that extglob is set:

shopt -s extglob

Now, we can match zero or more of any pattern with *(...). For example, let's create some files and match them:

$ touch logsheet logsheet2 logsheet23 logsheet234
$ echo logsheet*([0-9])
logsheet logsheet2 logsheet23 logsheet234

Documentation

According to man bash, bash offers the following features with extglob:

?(pattern-list)
Matches zero or one occurrence of the given patterns

*(pattern-list)
Matches zero or more occurrences of the given patterns

+(pattern-list)
Matches one or more occurrences of the given patterns

@(pattern-list)
Matches one of the given patterns

!(pattern-list)
Matches anything except one of the given patterns

Upvotes: 4

Related Questions