Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have an example:

echo "@article{gjn2010jucs, Author =   {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'

Is it possible to write a regular expression that selects the shorter pattern?

@article{gjn2010jucs,

Instead of a long pattern?:

@article{gjn2010jucs, Author =   {Grzegorz J. Nalepa},

I want to get this result:

Author =   {Grzegorz J. Nalepa},

EDIT:

I have another example:

echo ",article{gjn2010jucs, Author =   {Grzegorz J. Nalepa}, " | awk '{ sub(/,[^,]*,/,""); print }'

Is it possible to write a regular expression that selects the shorter pattern?

, Author =   {Grzegorz J. Nalepa},

Instead of a long pattern?:

,article{gjn2010jucs, Author =   {Grzegorz J. Nalepa},

I want to get this result:

,article{gjn2010jucs
share|improve this question
3  
Just as regex are inadequate for robust HTML parsing, they probably won't be able to do this kind of context-sensitive grammar parsing. However, if your set of inputs is fairly restricted and well-formed, you may be able to get away with regex as long as you declare what your restrictions are. For example you could look for Author following a comma and whitespace, followed by whitespace followed by = followed by whitespace followed by { followed by any non-} followed by }, although this requires (among other things) that you can't nest {} inside the = { ... } part. –  jw013 Oct 1 '12 at 17:02
    
@jw013, thank you for your explanation. Yet I will wait for suggestions of other users. –  nowy1 Oct 1 '12 at 17:51
add comment

4 Answers

up vote 6 down vote accepted

If you want to select @ and up to the first , after that, you need to specify it as @[^,]*,

That is @ followed by any number (*) of non-commas ([^,]) followed by a comma (,).

share|improve this answer
    
Thank you very much for the good response. In my editing I asked yet another example (see my edit). –  nowy1 Oct 2 '12 at 5:55
add comment

There is always a way. The given problem can be solved fairly easily by using commas as separator.

echo "@article{gjn2010jucs, Author =   {Grzegorz J. Nalepa}, " |
awk -F, '{sub(/^[ \t]/, "", $2); print $2}'

When the numbers of fields vary something slightly better is usually needed. In such case finding a stop words often pays off, as you can cut anything out from the line by using them. Within context of the example here's what I mean by stop words.

echo "@article{gjn2010jucs, Author =   {Grzegorz J. Nalepa}, " |
awk  '{sub(/.*Author/, "Author", $0); sub(/},.*/, "}", $0); print $0}'
share|improve this answer
add comment

sch's answer is good for basic and extended regexp (as found in most dialects of grep, sed, awk, etc)....it's what I would have answered if he hadn't beaten me to it :)

Perl also has a non-greedy operator which can be used in perl scripts and anything that uses PCRE ("Perl Compatible Regular Expressions"). e.g. also implemented in GNU grep's -P option.

PCRE is not identical to perl's regular expressions, but it is very close. It is a popular choice of RE library for many programs because it's very fast, and the perl enhancements to extended regexp are very useful.

from the perlre(1) man page:

       By default, a quantified subpattern is "greedy", that is, it will match
       as many times as possible (given a particular starting location) while
       still allowing the rest of the pattern to match.  If you want it to
       match the minimum number of times possible, follow the quantifier with
       a "?".  Note that the meanings don't change, just the "greediness":

           *?        Match 0 or more times, not greedily
           +?        Match 1 or more times, not greedily
           ??        Match 0 or 1 time, not greedily
           {n}?      Match exactly n times, not greedily (redundant)
           {n,}?     Match at least n times, not greedily
           {n,m}?    Match at least n but not more than m times, not greedily
share|improve this answer
    
Thank you for your explanation. –  nowy1 Oct 2 '12 at 5:56
add comment

There isn't a way in awk to do non-greedy matching. You may be able to get the desired output, though. sch's suggestion will work for that line. If you can't rely on a comma, but "Author" is always the start of the what you want, you could do this:

awk '{ sub(/@.*Author/,"Author"); print }'

If the number of characters preceding Author is always the same, you could do this:

awk '{ sub(/@.{21}/,""); print }'

You just need to know what your data looks like across the whole set.

share|improve this answer
    
Thank you for your example of a solution. –  nowy1 Oct 2 '12 at 5:58
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.