Поиск и замена в текстовой переменной с помощью регулярных выражений

Автор neft, 6 ноября 2011, 17:26

0 Пользователи и 1 гость просматривают эту тему.

neft

Добрый день!
Есть текстовая переменная
str1="RADIATION
Zalogin
21-11-2008"

Именно такая, с концами абзацев.

Вопрос в том, как с помощью регулярных выражений производить поиск и замену в этой переменной str1, т.е, например, заменить все концы абзацев на такой текст "<PARAGRAPH_BREAK>" и моместить результат в новую переменную str2?

Рыбка Рио

Именно регулярные выражения? Не знаю, но в любом случае, думаю можно самим написать функцию, которая преобразует регулярные выражения в обычные. А дальше - функция Replace.

REM  *****  BASIC  *****

Sub Main
p=chr(13)
str1="RADIATION"+p+"Zalogin"+p+"21-11-2008"
str2 = Replace(str1,p,"<PARAGRAPH_BREAK>")
msgbox str2
End Sub
ubuntu 12.04 + LibO3.6.0

neft

Вопрос касался именно регулярных выражений в текстовой переменной.

Но и ответ Клио неверный.

Windows и Linux сильно отличаются в этом плане.

PARAGRAPH_BREAK:
Windows - Chr(13) & Chr(10)
Linux - Chr(10) (???)

LINE_BREAK:
Windows - Chr(10)
Linux - Chr(10) (???)

Для иллюстрации сказанного прикладываю тестовый файл с разными вариантами Replace.

Если внимательно их проверить, то видно, что только в Windows результаты соответствуют ожидаемым.


PS. И сразу вопрос. Как написать макрос, работающий одинаково в Windows  и Linux?


[вложение удалено Администратором]

bormant

neft,
Цитата: neft от  6 ноября 2011, 16:26на такой текст "<PARAGRAPH_BREAK>"
Цитата: neft от  7 ноября 2011, 10:59PARAGRAPH_BREAK:
Windows - Chr(13) & Chr(10)
Linux - Chr(10)

LINE_BREAK:
Windows - Chr(10)
Linux - Chr(10)

Условия задачи меняются на ходу.
Автору на яд. Поддержать форум.

neft

Мне Клио сам предложил сменить задачу на Replace.
А там проблемы.

bormant

В условии были текстовые переменные, замена одного текста на другой.
Потом выясняется, что не текстовые переменные, а документ; замена не на текст, а вставка управляющих последовательностей; ещё что-то?

Если надеялись, что ThisComponent.getText().String отдаст все особенности текста документа -- зря, это только наиболее близкое текстовое представление, как уже убедились, не совсем полное, в частности, разрывы строк становятся неотличимы от конца абзаца.

Так что, с решаемой задачей всё же нужно определиться...
Автору на яд. Поддержать форум.

neft

В Windows ThisComponent.getText().String отдает все особенности текста документа!!!

В Linux - полная ерунда!!!

bormant

Скажем так, в версии OOo под Windows значение, возвращаемое ThisComponent.getText().String позволяет отличить разрыв строки от разрыва абзаца, поскольку первый представляет как chr(10), а второй как chr(13)&chr(10). В версии OOo под Linux оба представлены как chr(10).

Тем не менее, возвращаемое под Win от этого не становится меньшей ерундой. Смотреть в сторону разделителей строк, принятых в Windows/Unix/Mac, стандарта ASCII.
Одиночный chr(10) -- LF -- Line Feed -- прогон строки -- никогда не использовался в качестве общепринятого разрыва строки в DOS/Windows.
Автору на яд. Поддержать форум.

neft

Цитата: bormant от  7 ноября 2011, 12:35
В версии OOo под Linux оба представлены как chr(10).
Вот это и мешает их разделить, если нужно. Ведь в ООо они разделены.

Рыбка Рио

Если длина текста более кажется 64000 знаков, то
msgbox ThisComponent.Text.String
выдаст пустую строку.
С помощью метода gotoNextParagraph можно считывать параграфы,
TK = ThisComponent.Text.createTextCursor()
TK.gotoStart(false)
TK.gotoNextParagraph(true)
msgbox TK.String

и суммировать их, вставляя между ними <PARAGRAPH_BREAK>
ubuntu 12.04 + LibO3.6.0

Рыбка Рио

(хотя с переходом к сдедующему параграфу не совсем так, извините, есть ещё gotoStartOfParagraph, gotoEndOfParagraph ...)
ubuntu 12.04 + LibO3.6.0

Рыбка Рио

О! А можно ещё проще:
REM  *****  BASIC  *****

Sub Main
Doc = ThisComponent
SD = Doc.createSearchDescriptor()
SD.SearchRegularExpression = TRUE
SD.SearchString = ".+"
Results = Doc.findAll(SD)
str1=""
For i=0 to Results.Count-1
str1=str1+Results(i).String+"<PARAGRAPH BREAK>"
Next
msgbox str1
End Sub
ubuntu 12.04 + LibO3.6.0

neft

Этот вариант смешивает "конец абзаца" и "конец строки" в одну кучу, а это неправильно.
LINE_BREAK != PARAGRAPH_BREAK

Рыбка Рио

Тогда замените в коде ".+" на "(.|\n)+"

В итоге код может выглядеть вот так:
REM  *****  BASIC  *****

Sub Main
Doc = ThisComponent
SD = Doc.createSearchDescriptor()
SD.SearchRegularExpression = TRUE
SD.SearchString = "(.|\n)+"
Results = Doc.findAll(SD)
str1=""
stmp=""
For i=0 to Results.Count-1
stmp = Replace(Results(i).String,chr(10),"<LINE_BREAK>")
str1=str1+stmp+"<PARAGRAPH_BREAK>"
Next
msgbox str1
End Sub
ubuntu 12.04 + LibO3.6.0

neft

Спасибо! Вот это действительно настоящее решение!

stmp = Replace(Results(i).String,chr(10),"<LINE_BREAK>")
можно заменить на
stmp = Replace(Results(i).String,"\n","<LINE_BREAK>")

Если нужно заменить только "конец абзаца", не трогая "конец строки" (как в моей задаче), то
stmp = Results(i).String