Asked  9 Months ago    Answers:  5   Viewed   53 times

How to catch and filer the filename

I have tried in PHP using preg_replace_callback, which I dont how to use correctly.

function upcount_name_callback($matches) {
   //var_export($matches);
   $index = isset($matches[3]) ? intval($matches[3]) + 1 : 1;
   return '_' . $index;
}

$filename1 = 'news.jpg';
echo preg_replace_callback('/^(([^.]*?)(?:_([0-9]*))?)(?:.|$)/', 'upcount_name_callback', $filename1, 1);

$filename2 = 'aw_news_2.png';
echo preg_replace_callback('/^(([^.]*?)(?:_([0-9]*))?)(?:.|$)/', 'upcount_name_callback', $filename2, 1);

Output (wrong):

array (
  0 => 'news.',
  1 => 'news',
  2 => 'news',
  3 => '1',
)

_1jpg       <= wrong - filename1

.

array (
  0 => 'aw_news_2.',
  1 => 'aw_news_2',
  2 => 'aw_news',
  3 => '2',
)

_3png      <= wrong - filename2

Output (aright):

news_1       <= filename1

.

aw_news_3      <= filename2

 Answers

64
function my_replace_callback ($matches)
{
    $index = isset ($matches [1]) ? $matches [1] + 1 : 1;
    return "_$index";
}

$file = 'news.jpg';
$file = preg_replace_callback ('/(?:_([0-9]+))?..*$/', 'my_replace_callback', $file);
print ($file);

$file = 'aw_news.jpg';
$file = preg_replace_callback ('/(?:_([0-9]+))?..*$/', 'my_replace_callback', $file);
print ($file);

$file = 'news_4.jpg';
$file = preg_replace_callback ('/(?:_([0-9]+))?..*$/', 'my_replace_callback', $file);
print ($file);

$file = 'aw_news_5.jpg';
$file = preg_replace_callback ('/(?:_([0-9]+))?..*$/', 'my_replace_callback', $file);
print ($file);
Wednesday, March 31, 2021
 
mopsyd
answered 9 Months ago
15

This will work only for non-nested parentheses:

    $regex = <<<HERE
    /  "  ( (?:[^"\\]++|\\.)*+ ) "
     | '  ( (?:[^'\\]++|\\.)*+ ) '
     | ( ( [^)]*                  ) )
     | [s,]+
    /x
    HERE;

    $tags = preg_split($regex, $str, -1,
                         PREG_SPLIT_NO_EMPTY
                       | PREG_SPLIT_DELIM_CAPTURE);

The ++ and *+ will consume as much as they can and give nothing back for backtracking. This technique is described in perlre(1) as the most efficient way to do this kind of matching.

Wednesday, March 31, 2021
 
KingCrunch
answered 9 Months ago
89

Disclaimer: I'm not a PHP Internals expert (yet?) so this is all from my understanding, and not guaranteed to be 100% correct or complete. :)

So, firstly, the PHP 7 behaviour - which, I note, is also followed by HHVM - appears to be correct, and PHP 5 has a bug here. There should be no extra assign by reference behaviour here, because regardless of execution order, the result of the two calls to ++$i should never be the same.

The opcodes look fine; crucially, we have two temp variables $2 and $3, to hold the two increment results. But somehow, PHP 5 is acting as though we'd written this:

$i = 2;
$i++; $temp1 =& $i;
$i++; $temp2 =& $i;
echo $temp1 + $temp2; 

Rather than this:

$i = 2;
$i++; $temp1 = $i;
$i++; $temp2 = $i;
echo $temp1 + $temp2; 

Edit: It was pointed out on the PHP Internals mailing list that using multiple operations that modify a variable within a single statement is generally considered "undefined behaviour", and ++ is used as an example of this in C/C++.

As such, it's reasonable for PHP 5 to return the value it does for implementation / optimisation reasons, even if it is logically inconsistent with a sane serialization into multiple statements.

The (relatively new) PHP language specification contains similar language and examples:

Unless stated explicitly in this specification, the order in which the operands in an expression are evaluated relative to each other is unspecified. [...] (For example,[...] in the full expression $j = $i + $i++, whether the value of $i is the old or new $i, is unspecified.)

Arguably, this is a weaker claim than "undefined behaviour", since it implies they are evaluated in some particular order, but we're into nit-picking now.

phpdbg investigation (PHP 5)

I was curious, and want to learn more about the internals, so did some playing around using phpdbg.

No references

Running the code with $j = $i in place of $j =& $i, we start with 2 variables sharing an address, with a refcount of 2 (but no is_ref flag):

Address         Refs    Type            Variable
0x7f3272a83be8  2       (integer)       $i
0x7f3272a83be8  2       (integer)       $j

But as soon as you pre-increment, the zvals are separated, and only one temp var is sharing with $i, giving a refcount of 2:

Address         Refs    Type            Variable
0x7f189f9ecfc8  2       (integer)       $i
0x7f189f859be8  1       (integer)       $j

With reference assignment

When the variables have been bound together, they share an address, with a refcount of 2, and a by-ref marker:

Address         Refs    Type            Variable
0x7f9e04ee7fd0  2       (integer)       &$i
0x7f9e04ee7fd0  2       (integer)       &$j

After the pre-increments (but before the addition), the same address has a refcount of 4, showing the 2 temp vars erroneously bound by reference:

Address         Refs    Type            Variable
0x7f9e04ee7fd0  4       (integer)       &$i
0x7f9e04ee7fd0  4       (integer)       &$j

The source of the issue

Digging into the source on http://lxr.php.net, we can find the implementation of the ZEND_PRE_INC opcode:

  • PHP 5.6
  • PHP 7.0

PHP 5

The crucial line is this:

 SEPARATE_ZVAL_IF_NOT_REF(var_ptr);

So we create a new zval for the result value only if it is not currently a reference. Further down, we have this:

if (RETURN_VALUE_USED(opline)) {
    PZVAL_LOCK(*var_ptr);
    EX_T(opline->result.var).var.ptr = *var_ptr;
}

So if the return value of the decrement is actually used, we need to "lock" the zval, which following a whole series of macros basically means "increment its refcount", before assigning it as the result.

If we created a new zval earlier, that's fine - our refcount is now 2, 1 for the actual variable, plus 1 for the operation result. But if we decided not to, because we needed to hold a reference, we're just incrementing the existing reference count, and pointing at a zval which may be about to be changed again.

PHP 7

So what's different in PHP 7? Several things!

Firstly, the phpdbg output is rather boring, because integers are no longer reference counted in PHP 7; instead, a reference assignment creates an extra pointer, which itself has a refcount of 1, to the same address in memory, which is the actual integer. The phpdbg output looks like this:

Address            Refs    Type      Variable
0x7f175ca660e8     1       integer   &$i
int (2)
0x7f175ca660e8     1       integer   &$j
int (2)

Secondly, there is a special code path in the source for integers:

if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
    fast_long_increment_function(var_ptr);
    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
    }
    ZEND_VM_NEXT_OPCODE();
}

So if the variable is an integer (IS_LONG) and not a reference to an integer (IS_REFERENCE) then we can just increment it in place. If we then need the return value, we can copy its value into the result (ZVAL_COPY_VALUE).

If it's a reference, we won't hit that code, but rather than keeping references bound together, we have these two lines:

ZVAL_DEREF(var_ptr);
SEPARATE_ZVAL_NOREF(var_ptr);

The first line says "if it's a reference, follow it to its target"; this takes us from our "reference to an integer" to the integer itself. The second - I think - says "if it's something refcounted, and has more than one reference, create a copy of it"; in our case, this will do nothing, because the integer doesn't care about refcounts.

So now we have an integer we can decrement, that will affect all by-reference associations, but not by-value ones for refcounted types. Finally, if we want the return value of the increment, we again copy it, rather than just assigning it; and this time with a slightly different macro which will increase the refcount of our new zval if necessary:

ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
Wednesday, March 31, 2021
 
fret
answered 9 Months ago
52

The standard disclaimer applies: Parsing HTML with regular expressions is not ideal. Success depends on the well-formedness of the input on a character-by-character level. If you cannot guarantee this, the regex will fail to do the Right Thing at some point.

Having said that:

<ab[^>]*>(.*?)</a>   // match group one will contain the link text
Saturday, May 29, 2021
 
lewiguez
answered 7 Months ago
30

NumberPicker is not just for integers.. Even you can use Floats String etc.

see this and read about it.

for tutorials :

  • http://gafurbabu.wordpress.com/2012/03/29/android-number-picker-dialog/

And I had used NumberPicker long ago like this and it might be some use posting here:

    NumberPicker np;
    String nums[]= {"Select Fraction","1/64","1/32","3/64","1/16","5/64","3/32","7/64","1/8","9/64","5/32","11/64","3/16","13/64","7/32","15/64","1/4","17/64","9/32","19/64","5/16","21/64","11/32","23/64","3/8","25/64","13/32","27/64","7/16","29/64"};

            np = (NumberPicker) findViewById(R.id.np);

            np.setMaxValue(nums.length-1);
            np.setMinValue(0);
            np.setWrapSelectorWheel(false);
            np.setDisplayedValues(nums);
            np.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); 

You can make ArrayList of any datatype and assign it.

Thursday, September 16, 2021
 
sathiya
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share