Here's how I would have presented this question, with an SSCCE:
use strict;
use warnings;
use Test::More;
my @good = (
'aa1.2',
'aa1_bb2'
);
my @bad = (
'aa1_2',
'aa1_2bb',
'1aa'
);
my $re = qr/^[a-z][^_]*(_[a-z].*)?$/;
plan tests => @good + @bad;
for my $str (@good) {
like ($str, $re, "$str matched");
}
for my $str (@bad) {
unlike ($str, $re, "$str not matched");
}
Note that this is a working solution as well as a statement of the problem. See also How to ask better questions using Test::More and sample data. | [reply] [d/l] |
/_[a-z]+\d/
You haven't shown us what you tried. If you provide a small, self-contained example, that makes it much easier for us to try out the examples against your data. | [reply] [d/l] |
Your pattern does not match the second example: aa1_bb2
| [reply] |
Since I'm not going to test my regular expressions and since you don't seem to want to provide a SSCCE, let us think about a different approach, rephrasing your problem:
If your string contains an underscore, you want that underscore to be followed by letters and then a number.
If your string contains no underscore, you want to accept it.
When you lok at these two statements, it should be simple for you to encode that as two separate if statements.
If you really want to force this into one regular expression, consider a simple alternation:
/^([^_]+|[^_]+_[a-z]+\d[^_]*)$/
("Either the string contains no underscore, or it contains stuff that is no underscore, followed by an underscore, letters and a digit, and then no underscores again").
Of course, this is all vague since you don't provide code to discuss. | [reply] [d/l] [select] |
$ perl -E '"aa1_bb2" =~ /_[a-z]+\d/ && say "Yes, it does!"'
Yes, it does!
| [reply] [d/l] [select] |
#!/usr/bin/perl
# http://perlmonks.org/?node_id=1178340
use strict;
use warnings;
while(<DATA>)
{
print /^(?!.*_\d)/ ? " matched $_" : "not matched $_";
}
__DATA__
aa1.2
aa1_bb2
aa1_2
aa1_2bb
1aa
Your last test case '1aa' has no underscore and therefor by your rule should match.
Edit after your edit (I think)
/^(?!.*[-_]\d)/
| [reply] [d/l] [select] |
Thanks!!!
You're right: my specification was incomplete.
Extended specification: Strings starting with a number should not be matched as well
| [reply] |
#!/usr/bin/perl
# http://perlmonks.org/?node_id=1178340
use strict;
use warnings;
while(<DATA>)
{
print /^(?!.*(?:-|_|^)\d)/ ? " matched $_" : "not matched $_";
}
__DATA__
aa1.2
aa1_bb2
aa1_2
aa1_2bb
1aa
| [reply] [d/l] |
Hm. You've described what you don't want to match rather than what you do want to match, and what you've described doesn't correspond to the examples you've given.
Why should the last example not match given it doesn't contain a separator at all?
Updated with addition rule:
#! perl -slw
use strict;
my @good = qw[ aa1.2 aa1_bb2 ];
my @bad = qw[ aa1_2 aa1_2bb 1aa ];
my $re = qr[^[0-9]|^.*[_-][0-9]];
print $_, $_ !~ $re ? ' matches.' : ' doesnt match' for @good, @bad;
__END__
C:\test>junk
aa1.2 matches.
aa1_bb2 matches.
aa1_2 doesnt match
aa1_2bb doesnt match
1aa doesnt match
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
c:\@Work\Perl\monks>perl -wMstrict -le
"print 'perl version: ', $];
;;
my @t = qw(aa1.2 aa1_bb2 aa1_2 aa1_2bb 1aa);
;;
my $sep = qr{ [-_] }xms;
my $num = qr{ \d+ }xms;
my $ok = qr{ (?! (?: \A | $sep) $num) . }xms;
;;
for my $s (@t) {
print $s =~ m{ \A $ok* \z }xms ? ' ' : 'NO', qq{ match: '$s'};
}
"
perl version: 5.008009
match: 'aa1.2'
match: 'aa1_bb2'
NO match: 'aa1_2'
NO match: 'aa1_2bb'
NO match: '1aa'
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
G'day hoppfrosch,
[Your post has undergone a number of changes.
I didn't see the original.
The one I'm replying to has (what appears to be) three updates:
"Edit", "Edit2" and "Extended specification".]
"I'm looking for a regex-pattern, which should not match, when a certain pattern ... occurs within a string"
When checking for patterns that don't match, use '!~',
as described in "perlop: Binding Operators", like this:
$string !~ /$pattern/
"... separator (underscore or minus) followed by number followed by any string ..."
You need to be more specific in prosaic descriptions like this.
These are all numbers: 1, 10, 1.0, and so on.
I'll assume you mean a single digit (following the separator), /\d/;
if you need to be more specific than that, state your intent,
e.g. /\d{n,m}/, /[0-9]/ or /\d/a.
See "perlrecharclass: Digits" for further discussion.
These are all strings:
'', ' ', "\n", '1', '1.0', 'A', 'xyz', '%$#@', and so on.
I'll assume you're not referring to zero-length strings or newlines,
i.e. the first character after "number" matches /./.
Again, state your intent if mean something more specific,
e.g. /\S/, /\D/, and so on.
"What I hoped to work was: \A([A-Za-z1-9\.-_]*)(?:(?![-_]\d).)"
I really only wanted to comment on the bracketed character classes.
'[-_]' and '[_-]' are both fine:
the '-' is not special as the first (2nd, if 1st is a caret) or last character
(elsewhere, it denotes a range).
The '.' character is not special in a bracketed character class;
'[\.-_]' and '[.-_]' both mean the same thing:
the complete range of the 50 characters with decimal ASCII codes between 46 and 95, inclusive.
See "perlrecharclass: Bracketed Character Classes" for a lot more details on these points.
"String aa1_2 should not be matched"
Either that's wrong or your description is.
'aa1_2' neither starts with a number
nor has a separator followed by a number followed by a string.
Here's the regex that I think you don't want to match:
/(?:^\d|[_-]\d.)/
Here's a quick test:
$ perl -E 'my @x = qw{aa1.2 aa1_bb2 aa1_2 aa1_2bb 1aa}; $_ !~ /(?:^\d|
+[_-]\d.)/ && say for @x'
aa1.2
aa1_bb2
aa1_2
| [reply] [d/l] [select] |
Your specification is so vague that it is unlikely that a proposed solution will do what you want even if does pass your five test cases.
Do you mean an undefined separator followed by either a minus or an underscore (or are they your definition of 'separator')? I do not see either in the first test.
Does 'number' mean number as perl defines number or does it mean one decimal digit?
Can we assume that 'any string' does not include the null string?
Your examples of failures should include an explanation of why you expect them to fail.
| [reply] |