문제

I would like to tell the difference between a number 1 and string '1'.

The reason that I want to do this is because I want to determine the number of capturing parentheses in a regular expression after a successful match. According the perlop doc, a list (1) is returned when there are no capturing groups in the pattern. So if I get a successful match and a list (1) then I cannot tell if the pattern has no parens or it has one paren and it matched a '1'. I can resolve that ambiguity if there is a difference between number 1 and string '1'.

도움이 되었습니까?

해결책

For example, bitwise operators behave differently for strings and integers:

~1 = 18446744073709551614

~'1' = Î ('1' = 0x31, ~'1' = ~0x31 = 0xce = 'Î')

#!/usr/bin/perl

($b) = ('1' =~ /(1)/);
print isstring($b) ? "string\n" : "int\n";
($b) = ('1' =~ /1/);
print isstring($b) ? "string\n" : "int\n";

sub isstring() {
    return ($_[0] & ~$_[0]);
}

isstring returns either 0 (as a result of numeric bitwise op) which is false, or "\0" (as a result of bitwise string ops, set perldoc perlop) which is true as it is a non-empty string.

다른 팁

You can tell how many capturing groups are in the last successful match by using the special @+ array. $#+ is the number of capturing groups. If that's 0, then there were no capturing parentheses.

If you want to know the number of capture groups a regex matched, just count them. Don't look at the values they return, which appears to be your problem:

You can get the count by looking at the result of the list assignment, which returns the number of items on the right hand side of the list assignment:

my $count = my @array = $string =~ m/.../g;

If you don't need to keep the capture buffers, assign to an empty list:

my $count = () = $string =~ m/.../g;

Or do it in two steps:

my @array = $string =~ m/.../g;
my $count = @array;

You can also use the @+ or @- variables, using some of the tricks I show in the first pages of Mastering Perl. These arrays have the starting and ending positions of each of the capture buffers. The values in index 0 apply to the entire pattern, the values in index 1 are for $1, and so on. The last index, then, is the total number of capture buffers. See perlvar.

Perl converts between strings and numbers automatically as needed. Internally, it tracks the values separately. You can use Devel::Peek to see this in action:

use Devel::Peek;
$x = 1;
$y = '1';
Dump($x);
Dump($y);

The output is:

SV = IV(0x3073f40) at 0x3073f44
  REFCNT = 1
  FLAGS = (IOK,pIOK)
  IV = 1
SV = PV(0x30698cc) at 0x3073484
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x3079bb4 "1"\0
  CUR = 1
  LEN = 4

Note that the dump of $x has a value for the IV slot, while the dump of $y doesn't but does have a value in the PV slot. Also note that simply using the values in a different context can trigger stringification or nummification and populate the other slots. e.g. if you did $x . '' or $y + 0 before peeking at the value, you'd get this:

SV = PVIV(0x2b30b74) at 0x3073f44
  REFCNT = 1
  FLAGS = (IOK,POK,pIOK,pPOK)
  IV = 1
  PV = 0x3079c5c "1"\0
  CUR = 1
  LEN = 4

At which point 1 and '1' are no longer distinguishable at all.

Check for the definedness of $1 after a successful match. The logic goes like this:

  • If the list is empty then the pattern match failed
  • Else if $1 is defined then the list contains all the catpured substrings
  • Else the match was successful, but there were no captures

Your question doesn't make a lot of sense, but it appears you want to know the difference between:

$a = "foo"; 
@f = $a =~ /foo/; 

and

$a = "foo1"; 
@f = $a =~ /foo(1)?/; 

Since they both return the same thing regardless if a capture was made.

The answer is: Don't try and use the returned array. Check to see if $1 is not equal to ""

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top