0

I have a String variable containing something like ABCD.asd.qwe.com:/dir1. I want to extract the ABCD portion i.e. the portion from beginning till the first appearance of .. The problem is that there can be almost any characters (only alphanumeric) of any length before the .. So I created this regexp.

if($arg =~ /(.*?\.?)/)
{
    my $temp_name = $1;
}

However it is giving me blank string. The logic is that :

.*? - any character non-greedily
\.? - till first or none appearance of .

What could be wrong?

7
  • Are you tryint to extract ABCD or ABCD.? Will the . always be there in the input? Commented May 6, 2013 at 9:25
  • I want to extract only ABCD & not including the dot. Commented May 6, 2013 at 9:28
  • What about my second question. Will there always be a . in the input? Commented May 6, 2013 at 10:08
  • if you are asking whether the input will be .ABCD.asd.... then the answer is no. Commented May 6, 2013 at 10:16
  • 1
    Then all that's needed is /^([^.]*)/. No need to for any lookaheads Commented May 6, 2013 at 19:50

4 Answers 4

3

You can instead use negative character class like this

^[^.]+

[^.] would match any character except .

[^.]+ would match 1 to many characters(except .)

^ depicts the start of string

OR

^.+?(?=\.|$)

(?=) is a lookahead which checks for a particular pattern after the current position..So for text abcdad with regex a(?=b) only a would match

$ depicts the end of line(if used with multiline option) or end of string(if used with singleline option)

Sign up to request clarification or add additional context in comments.

7 Comments

Hey @Anirudh, both the solutions are working! Thanks man! But can you please explain the logic behind that?
@Cool_Coder The logic is very simple. The first ^ means "the string must start here". The next [^.]+ means "any character that isn't a period, repeated 1 or more times." Hence it selects up until the first period.
@Anirudh so ^[^x]+ would match any character from start till the first appearance of x, right?
@Cool_Coder it would match till the last appearance of character which is not ...so it would match everything if there's no .
I meant if instead I used ^[^C]+ then this would catch AB right?
|
3

\.? doesn't mean "till first or none appearance of .". It means "a . here or not".


If the first character of the string is .:

  • .*? matches 0 chars at position 0.
  • \.? matches 1 char at position 0.

$1 contains ..


If the first character of the string isn't .:

  • .*? matches 0 chars at position 0.
  • \.? matches 0 chars at position 0.

$1 is empty.


To match ABCD, the following would do:

/^(.*?)\./

However, I hate the non-greedy modifier. It's fragile, in the sense that it stops doing what you want if you use two in the same pattern. I'd use the following instead ("match non-periods"):

/^([^.]*)\./

or even just

/^([^.]*)/

2 Comments

(The ^ isn't necessary, but it's a good habit as it can be prevent a crazy amount of backtracking on failure.)
Thanks for explaining the incorrectness of my initial approach.
2
use strict;

my $string = "ABCD.asd.qwe.com:/dir1";

$string =~ /([^.]+)/;
my $capture = $1;
print"$capture\n";

OR you can also use Split function like,

my $sub_string = ( split /\./, $string )[0];
print"$sub_string\n";

Note in general: For the explaination of Regex (understanding the complex Regex), take a look at YAPE::Regex::Explain module.

1 Comment

my ($capture) = $string =~ /^([^.]+)/; would be more robust. (Bonus: doesn't use global vars.)
0

This should work:

if($arg =~ /(.*?)\..+/)
{
    my $temp_name = $1; 
} 

That would match anything before the first . . You could change the .+ to .* if your input may end after the first .. You could change the first .*? to .+? if you are sure that there is always at least one character before the first ..

1 Comment

The added .+ is useless. Firstly, it's the same as just .. Secondly, all it does is make sure the . is followed by a non-newline, and the OP did not express any interest in verifying that. So why did you add it?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.