Я создал следующее регулярное выражение с идеей извлечь последний элемент в скобках. Посмотрите, что если у меня есть только одна скобка, она работает нормально, но если у меня есть две скобки, она извлекает первую (что является ошибкой) или извлекает скобки.

Ты знаешь как это решить?

    tmp= spark.createDataFrame(
    [
        (1, 'foo (123) oiashdj (hi)'), 
        (2, 'bar oiashdj (hi)'),
    ],
    ['id', 'txt'] 
)


tmp = tmp.withColumn("old", regexp_extract(col("txt"), "(?<=\().+?(?=\))", 0));

tmp = tmp.withColumn("new", regexp_extract(col("txt"), "\(([^)]+)\)?$", 0));

tmp.show()

+---+--------------------+---+----+
| id|                 txt|old| new| needed
+---+--------------------+---+----+
|  1|foo (123) oiashdj...|123|(hi)|  hi 
|  2|    bar oiashdj (hi)| hi|(hi)|  hi
+---+--------------------+---+----+
1
Raymont 19 Фев 2020 в 18:31

2 ответа

Лучший ответ

Чтобы извлечь подстроку в скобках без других скобок внутри в конце строки, вы можете использовать

tmp = tmp.withColumn("new", regexp_extract(col("txt"), r"\(([^()]+)\)$", 1));

< Сильный > Подробнее

  • \( - соответствует (
  • ([^()]+) - включает в группу 1 любые символы 1+, кроме ( и )
  • \) - символ )
  • $ - в конце строки.

Аргумент 1 указывает regexp_extract извлечь значение группы 1.

См. демонстрацию regex в Интернете.

ПРИМЕЧАНИЕ . Чтобы разрешить конечные пробелы, добавьте \s* прямо перед $: r"\(([^()]+)\)\s*$"

ПРИМЕЧАНИЕ2 . Чтобы сопоставить последнее вхождение такой подстроки в более длинной строке с точно таким же кодом, как указано выше, используйте

r"(?s).*\(([^()]+)\)"

.* будет захватывать весь текст до конца, а затем обратное отслеживание сделает всю работу.

2
Wiktor Stribiżew 19 Фев 2020 в 15:39

Это должно работать. Используйте это с однострочным флагом.

\([^\(\)]*?\)(?!.*\([^\(\)]*?\))

https://regex101.com/r/Qrnlf3/1

1
SG Tech Edge 19 Фев 2020 в 15:39