Skip to content

Commit

Permalink
[expressions] Allow non-greedy regex by switching to QRegularExpression
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Oct 26, 2016
1 parent 323c658 commit 6f82740
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 9 deletions.
2 changes: 1 addition & 1 deletion resources/function_help/json/regexp_match
Expand Up @@ -3,7 +3,7 @@
"type": "function",
"description": "Returns true if any part of a string matches the supplied regular expression.",
"arguments": [ {"arg":"input_string","description":"the string to test against the regular expression"},
{"arg":"regex","description":"The regular expression to test against. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."}
{"arg":"regex","description":"The regular expression to test against. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character)."}
],
"examples": [ { "expression":"regexp_match('QGIS ROCKS','\\\\\\\\sROCKS')", "returns":"true"}]
}
2 changes: 1 addition & 1 deletion resources/function_help/json/regexp_replace
Expand Up @@ -3,7 +3,7 @@
"type": "function",
"description": "Returns a string with the supplied regular expression replaced.",
"arguments": [ {"arg":"input_string","description":"the string to replace matches in"},
{"arg":"regex","description":"The regular expression to replace. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."},
{"arg":"regex","description":"The regular expression to replace. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character)."},
{"arg":"replacement","description":"The string that will replace any matching occurrences of the supplied regular expression. Captured groups can be inserted into the replacement string using \\\\\\\\1, \\\\\\\\2, etc."}
],
"examples": [ { "expression":"regexp_replace('QGIS SHOULD ROCK','\\\\\\\\sSHOULD\\\\\\\\s',' DOES ')", "returns":"'QGIS DOES ROCK'"}]
Expand Down
2 changes: 1 addition & 1 deletion resources/function_help/json/regexp_substr
Expand Up @@ -3,7 +3,7 @@
"type": "function",
"description": "Returns the portion of a string which matches a supplied regular expression.",
"arguments": [ {"arg":"input_string","description":"the string to find matches in"},
{"arg":"regex","description":"The regular expression to match against. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character). Non-greedy regular expressions are not supported."}
{"arg":"regex","description":"The regular expression to match against. Backslash characters must be double escaped (eg \"\\\\\\\\s\" to match a white space character)."}
],
"examples": [ { "expression":"regexp_substr('abc123','(\\\\\\\\d+)')", "returns":"'123'"}]
}
12 changes: 6 additions & 6 deletions src/core/qgsexpression.cpp
Expand Up @@ -1225,7 +1225,7 @@ static QVariant fcnRegexpReplace( const QVariantList& values, const QgsExpressio
QString regexp = getStringValue( values.at( 1 ), parent );
QString after = getStringValue( values.at( 2 ), parent );

QRegExp re( regexp );
QRegularExpression re( regexp );
if ( !re.isValid() )
{
parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
Expand All @@ -1239,7 +1239,7 @@ static QVariant fcnRegexpMatch( const QVariantList& values, const QgsExpressionC
QString str = getStringValue( values.at( 0 ), parent );
QString regexp = getStringValue( values.at( 1 ), parent );

QRegExp re( regexp );
QRegularExpression re( regexp );
if ( !re.isValid() )
{
parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
Expand All @@ -1253,19 +1253,19 @@ static QVariant fcnRegexpSubstr( const QVariantList& values, const QgsExpression
QString str = getStringValue( values.at( 0 ), parent );
QString regexp = getStringValue( values.at( 1 ), parent );

QRegExp re( regexp );
QRegularExpression re( regexp );
if ( !re.isValid() )
{
parent->setEvalErrorString( QObject::tr( "Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
return QVariant();
}

// extract substring
( void )re.indexIn( str );
if ( re.captureCount() > 0 )
QRegularExpressionMatch match = re.match( str );
if ( match.hasMatch() )
{
// return first capture
return QVariant( re.capturedTexts().at( 1 ) );
return QVariant( match.captured( 0 ) );
}
else
{
Expand Down
4 changes: 4 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -822,10 +822,14 @@ class TestQgsExpression: public QObject
QTest::newRow( "length" ) << "length('HeLLo')" << false << QVariant( 5 );
QTest::newRow( "replace" ) << "replace('HeLLo', 'LL', 'xx')" << false << QVariant( "Hexxo" );
QTest::newRow( "regexp_replace" ) << "regexp_replace('HeLLo','[eL]+', '-')" << false << QVariant( "H-o" );
QTest::newRow( "regexp_replace greedy" ) << "regexp_replace('HeLLo','(?<=H).*L', '-')" << false << QVariant( "H-o" );
QTest::newRow( "regexp_replace non greedy" ) << "regexp_replace('HeLLo','(?<=H).*?L', '-')" << false << QVariant( "H-Lo" );
QTest::newRow( "regexp_replace cap group" ) << "regexp_replace('HeLLo','(eL)', 'x\\\\1x')" << false << QVariant( "HxeLxLo" );
QTest::newRow( "regexp_replace invalid" ) << "regexp_replace('HeLLo','[[[', '-')" << true << QVariant();
QTest::newRow( "substr" ) << "substr('HeLLo', 3,2)" << false << QVariant( "LL" );
QTest::newRow( "substr outside" ) << "substr('HeLLo', -5,2)" << false << QVariant( "" );
QTest::newRow( "regexp_substr" ) << "regexp_substr('abc123','(\\\\d+)')" << false << QVariant( "123" );
QTest::newRow( "regexp_substr non-greedy" ) << "regexp_substr('abc123','(\\\\d+?)')" << false << QVariant( "1" );
QTest::newRow( "regexp_substr no hit" ) << "regexp_substr('abcdef','(\\\\d+)')" << false << QVariant( "" );
QTest::newRow( "regexp_substr invalid" ) << "regexp_substr('abc123','([[[')" << true << QVariant();
QTest::newRow( "strpos" ) << "strpos('Hello World','World')" << false << QVariant( 7 );
Expand Down

1 comment on commit 6f82740

@nirvn
Copy link
Contributor

@nirvn nirvn commented on 6f82740 Oct 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice.

Please sign in to comment.