[expressions][feature] Add ltrim/rtrim functions

Allows trimming spaces or other characters from just the
start or end of strings
This commit is contained in:
Nyall Dawson 2023-02-10 11:45:56 +10:00
parent 12d6b44e7e
commit 3c91c624c8
4 changed files with 92 additions and 0 deletions

View File

@ -0,0 +1,25 @@
{
"name": "ltrim",
"type": "function",
"groups": ["String"],
"description": "Removes the longest string containing only the specified characters (a space by default) from the start of string.",
"arguments": [{
"arg": "string",
"description": "string to trim"
},
{
"arg": "characters",
"description": "characters to trim",
"optional": true,
"default": "' '"
}],
"examples": [{
"expression": "ltrim(' hello world ')",
"returns": "'hello world '"
},
{
"expression": "ltrim('zzzytest', 'xyz')",
"returns": "'test'"
}],
"tags": ["removes", "leading", "whitespace", "spaces", "tabs"]
}

View File

@ -0,0 +1,25 @@
{
"name": "rtrim",
"type": "function",
"groups": ["String"],
"description": "Removes the longest string containing only the specified characters (a space by default) from the end of string.",
"arguments": [{
"arg": "string",
"description": "string to trim"
},
{
"arg": "characters",
"description": "characters to trim",
"optional": true,
"default": "' '"
}],
"examples": [{
"expression": "rtrim(' hello world ')",
"returns": "' hello world'"
},
{
"expression": "rtrim('testxxzx', 'xyz')",
"returns": "'test'"
}],
"tags": ["removes", "whitespace", "spaces", "tabs", "trailing"]
}

View File

@ -1342,6 +1342,28 @@ static QVariant fcnTrim( const QVariantList &values, const QgsExpressionContext
return QVariant( str.trimmed() );
}
static QVariant fcnLTrim( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
const QRegularExpression re( QStringLiteral( "^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
str.replace( re, QString() );
return QVariant( str );
}
static QVariant fcnRTrim( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
const QRegularExpression re( QStringLiteral( "([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
str.replace( re, QString() );
return QVariant( str );
}
static QVariant fcnLevenshtein( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
@ -8159,6 +8181,12 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< new QgsStaticExpressionFunction( QStringLiteral( "upper" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ), fcnUpper, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "title" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ), fcnTitle, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "trim" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ), fcnTrim, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "ltrim" ), QgsExpressionFunction::ParameterList()
<< QgsExpressionFunction::Parameter( QStringLiteral( "string" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "characters" ), true, QStringLiteral( " " ) ), fcnLTrim, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "rtrim" ), QgsExpressionFunction::ParameterList()
<< QgsExpressionFunction::Parameter( QStringLiteral( "string" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "characters" ), true, QStringLiteral( " " ) ), fcnRTrim, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "levenshtein" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string1" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "string2" ) ), fcnLevenshtein, QStringLiteral( "Fuzzy Matching" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "longest_common_substring" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string1" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "string2" ) ), fcnLCS, QStringLiteral( "Fuzzy Matching" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "hamming_distance" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string1" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "string2" ) ), fcnHamming, QStringLiteral( "Fuzzy Matching" ) )

View File

@ -1678,6 +1678,20 @@ class TestQgsExpression: public QObject
QTest::newRow( "title" ) << "title(' HeLlO WORLD ')" << false << QVariant( " Hello World " );
QTest::newRow( "trim" ) << "trim(' Test String ')" << false << QVariant( "Test String" );
QTest::newRow( "trim empty string" ) << "trim('')" << false << QVariant( "" );
QTest::newRow( "ltrim none" ) << "ltrim('trim ')" << false << QVariant( "trim " );
QTest::newRow( "ltrim space" ) << "ltrim(' trim ')" << false << QVariant( "trim " );
QTest::newRow( "ltrim empty string" ) << "ltrim('')" << false << QVariant( "" );
QTest::newRow( "ltrim('zzzytrim', 'xyz')" ) << "ltrim('zzzytrim', 'xyz')" << false << QVariant( "trim" );
QTest::newRow( "ltrim('zzzytrim', 'a')" ) << "ltrim('zzzytrim', 'a')" << false << QVariant( "zzzytrim" );
QTest::newRow( "ltrim('zzzytrim', '[(*')" ) << "ltrim('zzzytrim', '[(*')" << false << QVariant( "zzzytrim" );
QTest::newRow( "ltrim('))(* *[[trim', '[())* ')" ) << "ltrim('))(* *[[trim', '[())* ')" << false << QVariant( "trim" );
QTest::newRow( "rtrim none" ) << "rtrim(' trim')" << false << QVariant( " trim" );
QTest::newRow( "rtrim space" ) << "rtrim(' trim ')" << false << QVariant( " trim" );
QTest::newRow( "rtrim empty string" ) << "rtrim('')" << false << QVariant( "" );
QTest::newRow( "rtrim('trimzzzy', 'xyz')" ) << "rtrim('trimzzzy', 'xyz')" << false << QVariant( "trim" );
QTest::newRow( "rtrim('trimzzzy', 'a')" ) << "rtrim('trimzzzy', 'a')" << false << QVariant( "trimzzzy" );
QTest::newRow( "rtrim('trimzzzy', '[(*')" ) << "rtrim('trimzzzy', '[(*')" << false << QVariant( "trimzzzy" );
QTest::newRow( "rtrim('trim)(* *[[', '[()* ')" ) << "rtrim('trim)(* *[[', '[()* ')" << false << QVariant( "trim" );
QTest::newRow( "char" ) << "char(81)" << false << QVariant( "Q" );
QTest::newRow( "ascii single letter" ) << "ascii('Q')" << false << QVariant( 81 );
QTest::newRow( "ascii word" ) << "ascii('QGIS')" << false << QVariant( 81 );