3

This is based on Run regexp in PyQGIS script? and Search and Replace text in All Fields in QGIS 3

I am trying to modify the code to allow more complex replacements using regex but am unsure how to structure the re.sub function

See https://regex101.com/r/OX1W3b/2/ for one example...

1. DIMENSIONS:  | ORIGIN: | Position corrected and IL (0) was changed based on RPS: 3482 -230
2. DIMENSIONS: 2 x 1350 RCP | ORIGIN: PCD13180 | Position corrected and IL (0) was changed based on RPS: 1390 -20800/1350RCP
3. DIMENSIONS: 3 x 375 RCP | ORIGIN:
4. DIMENSIONS:  | ORIGIN:
5. Review attribution | DIMENSIONS:  | ORIGIN:

Where there is no value after DIMENSIONS or ORIGIN it should be deleted so...

1. Position corrected and IL (0) was changed based on RPS: 3482 -230
2. DIMENSIONS: 2 x 1350 RCP | ORIGIN: PCD13180 | Position corrected and IL (0) was changed based on RPS: 1390 -20800/1350RCP
3. DIMENSIONS: 3 x 375 RCP
4. 
5. Review attribution

Here's the current code - see line 10 and 33 for the regex based commands.

#Use in QGIS 3 python console
#Search and replace text in all fields of all layers
#Also allows regex use
import re

#Based on https://gis.stackexchange.com/questions/317855/search-and-replace-text-in-all-fields-in-qgis-3

#set text to search for and replace with.
searchText = "DIM"
regexText = ".*(DIMENSIONS:  \|)"
replaceText = ""

#run on all layers
layers = QgsProject.instance().mapLayers()

for layer_id, layer in layers.items():
    i=1
    print("Layer: %s" % (layer.name()))
    # get data provider
    dpr = layer.dataProvider()
    for field in layer.fields():
        fieldName=field.name()

        for feature in layer.getFeatures():
            inText = str(feature[fieldName])
            # get field index
            fieldIndex = layer.fields().indexFromName(fieldName)
            #print ("Checking %s" % (inText))

            if searchText in inText:
                # change inText
                print ("%s . REPLACED: %s in %s with %s in column: %s" % (i, searchText, inText, replaceText, fieldName))
                #outText = inText.replace(searchText, replaceText)
                outText = re.sub(fieldName, regexText, replaceText)
                i+=1
                # save changes
                dpr.changeAttributeValues({feature.id(): {fieldIndex: outText}})
print ("Completed")

UPDATE when using regexText = ".*(DIMENSIONS: )(\| ORIGIN: ?\|? ?)" enter image description here

I think we need to deal with each key (DIMENSIONS:, ORIGIN: etc) without value separately as there are others and it overly complicates the regex. So forget about ORIGIN: and need to look at code that will just clean up DIMENSIONS as per the examples. The same can then be used for ORIGIN once we get it right.

Basically we just need to get rid of the key (DIMENSIONS:) when it doesn't have text after it and before the | seperator. Any text before or after should be retained as per the examples.

I think the issue is in the use of "outText = re.sub(fieldName, regexText, replaceText)" because the value in replaceText should be the capture string from the regex not the string in replaceText.

1
  • Basically in field calc it would be something like --- regexp_replace(fieldName, 'RegexPattern','ReplaceText') but not sure what to do in pyQGIS or this purplelinux.co.nz/?p=96
    – GeorgeC
    Commented Apr 15, 2019 at 11:55

1 Answer 1

1

Try:

((?<=^...)(DIMENSIONS:  \|))|( \| DIMENSIONS: )|( ?\|? ORIGIN:$)|( ?ORIGIN: \| )

But it's ugly..

3
  • thanks I tried but it removed everything when the regex was found... see updated question. I think the issue is the structure of the outtext = re.sub command.
    – GeorgeC
    Commented Apr 15, 2019 at 6:14
  • Sorry, I updated my original answer - it's pretty ugly but works on regex101.
    – Nav
    Commented Apr 15, 2019 at 6:34
  • you are right, it does work in regex101 however when you run the script "DIMENSIONS: | ORIGIN: 2010 PureData Survey" comes out as no value rather than "ORIGIN: 2010 PureData Survey" ---- I think the issue is in the use of "outText = re.sub(fieldName, regexText, replaceText)" because the value in replaceText should be the capture string from the regex not the string in replaceText. ALSO can we forget about the origin and focus on getting rid of "DIMENSIONS: " where there is no value before the pipe, as I think this is confusing this example use case...see regex101.com/r/OX1W3b/5
    – GeorgeC
    Commented Apr 15, 2019 at 8:39

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.