| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Замена символов в строке

Замена символов в строке

Ответ
Поиск в этой теме
Непрочитано 14.12.2018, 17:50 #1
Замена символов в строке
tsetse
 
Инженер-конструктор
 
Москва
Регистрация: 25.12.2015
Сообщений: 77

Добрый день!
Как строку
Код:
[Выделить все]
 \\AcExpr (I10*$G$8*$G$7) \\f \"%pr2%lu2\"
привести к виду
Код:
[Выделить все]
 \\AcExpr (I10*$G$8*$G$7) \\f "%pr2%lu2"
т.е. заменить \" на ". Пытался так
Код:
[Выделить все]
 (vl-string-subst """ "\"" Temp_List_Name)
и через
Код:
Однако (chr 34) выдает \"
Просмотров: 3295
 
Непрочитано 14.12.2018, 18:20
#2
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


а разве это не экранирующий кавычку слэш?
Сергей812 вне форума  
 
Автор темы   Непрочитано 14.12.2018, 18:22
#3
tsetse

Инженер-конструктор
 
Регистрация: 25.12.2015
Москва
Сообщений: 77


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
а разве это не экранирующий кавычку слэш?
Да, это он. Лиспом я извлекаю строку с экранирующим слешем. Мне нужно собрать строку в которой нет экранирующего слеша. Просто кавычки
То есть фактически превратить строку
Код:
в
Код:
tsetse вне форума  
 
Непрочитано 14.12.2018, 18:47
#4
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


думаю, что это так отображает... попробуйте в полученной строке найти этот слэш функцией vl-string-position
Сергей812 вне форума  
 
Автор темы   Непрочитано 14.12.2018, 19:03
#5
tsetse

Инженер-конструктор
 
Регистрация: 25.12.2015
Москва
Сообщений: 77


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
думаю, что это так отображает... попробуйте в полученной строке найти этот слэш функцией vl-string-position
Не вышло(((
Код:
автокад выводит как
Получилось вот так
Код:
[Выделить все]
 (vl-string-subst "\U+0022" (chr 34) Temp_List_Name)
tsetse вне форума  
 
Непрочитано 14.12.2018, 19:06
#6
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


Естественно не вышло - я предлагал проверить, находит ли этот слеш в результирующей строке и успокоиться - поняв, что комбинация \" воспринимается как кавычка без слэша.
Сергей812 вне форума  
 
Автор темы   Непрочитано 14.12.2018, 20:13
#7
tsetse

Инженер-конструктор
 
Регистрация: 25.12.2015
Москва
Сообщений: 77


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
Естественно не вышло - я предлагал проверить, находит ли этот слеш в результирующей строке и успокоиться - поняв, что комбинация \" воспринимается как кавычка без слэша.
Да, спасибо! Я просто нашел проблему там, где ее нет. Буду умнее)
tsetse вне форума  
 
Непрочитано 14.12.2018, 20:25
#8
koMon


 
Блог
 
Регистрация: 26.09.2017
Сообщений: 1,665


в лиспе значение стоковой переменной ограничивается кавычками. соответственно если значение строковой переменной содержит каычку(и), то в виду ранее сказанного эта кавычка должна иметь вид \".
в примере вышее
должна работать конструкция
(vl-string-ranslatet "\"" "" Temp_List_Name), то есть заменяющая все кавычки на ничто или
конструкция
(vl-string-subst "" "\"" Temp_List_Name), заменяющая первую встретившуюся кавычку опять же на ничто

упс...
koMon вне форума  
 
Автор темы   Непрочитано 14.12.2018, 20:36
#9
tsetse

Инженер-конструктор
 
Регистрация: 25.12.2015
Москва
Сообщений: 77


Цитата:
Сообщение от koMon Посмотреть сообщение
в лиспе значение стоковой переменной ограничивается кавычками. соответственно если значение строковой переменной содержит каычку(и), то в виду ранее сказанного эта кавычка должна иметь вид \".
в примере вышее
должна работать конструкция
(vl-string-ranslatet "\"" "" Temp_List_Name), то есть заменяющая все кавычки на ничто или
конструкция
(vl-string-subst "" "\"" Temp_List_Name), заменяющая первую встретившуюся кавычку опять же на ничто
упс...
Я хотел заменить \" в строке на ". Но оказалось, необходимости в этом нет. Автокад великолено прожевал \".
P.S.На "ничто" заменить получалось)
tsetse вне форума  
 
Непрочитано 15.12.2018, 21:40
#10
===AAA===


 
Регистрация: 15.08.2005
г. Норильск
Сообщений: 451


Всем привет!

Больно уж название у темы хорошее - не хочется дубляжа.
Задам и я свой вопрос.
Здесь.

Если замена "хоть чего" на "хоть что" в обычных текстах
и атрибутах вопросов как бы не вызывает, то на MTEXT'ах
(далее - МТ) вылазят ньюансы.

Допустим, есть в чертехе куча МТ вида

Блок АС18-2
Блок АС18-3
Блок АС18-n

Вот именно так они и выглядят - часть текста черная, а часть
красная. Или - ещё более изощрённый вариант, его средствами
форума не изобразить - "18" выделена не цветом, а шириной.

Задача - заменить "С1" на "В2". Т.е. замена должна проходить
по границе форматирования МТ, где стоит какой-то произвольный
управляющий код.

Задача "не высосана из пальца", а реальная - сам был немерянно
удивлён, когда столкнулся с такой необходимостью.

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

Но вот интересно - а в принципе задача с сохранением исходного
форматирования МТ решается?

Если есть соображения насчёт алгоритма решения - с удовольствием
прочитаю и попробую реализовать.
__________________
Счастливо, Алексей!
===AAA=== вне форума  
 
Автор темы   Непрочитано 16.12.2018, 00:41
#11
tsetse

Инженер-конструктор
 
Регистрация: 25.12.2015
Москва
Сообщений: 77


Цитата:
Сообщение от ===AAA=== Посмотреть сообщение
Всем привет!

Больно уж название у темы хорошее - не хочется дубляжа.
Задам и я свой вопрос.

Допустим, есть в чертехе куча МТ вида

Блок АС18-2
Блок АС18-3
Блок АС18-n

Вот именно так они и выглядят - часть текста черная, а часть
красная. Или - ещё более изощрённый вариант, его средствами
форума не изобразить - "18" выделена не цветом, а шириной.

Задача - заменить "С1" на "В2". Т.е. замена должна проходить
по границе форматирования МТ, где стоит какой-то произвольный
управляющий код..
Добрый вечер! Прикрепите пожалуйста двг с двумя мтекстами, до замены и что должно быть после замены. Самый общий случай, если не трудно.
tsetse вне форума  
 
Непрочитано 16.12.2018, 01:33
1 | #12
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


Цитата:
Сообщение от tsetse Посмотреть сообщение
Добрый вечер! Прикрепите пожалуйста двг с двумя мтекстами, до замены и что должно быть после замены. Самый общий случай, если не трудно
внутри мультитекста выделите фрагмент и измените ему высоту, цвет и т.д. А результат - это что делает команда _find в режиме замены текста при выделенном объекте.

----- добавлено через ~17 ч. -----
Цитата:
Сообщение от ===AAA=== Посмотреть сообщение
Если есть соображения насчёт алгоритма решения - с удовольствием
прочитаю и попробую реализовать.
Набросал код на .Net, оформленный как лисп-функция. Простое форматирование и служебные символы он "прожевал", сильно не тестил. В каких то случаях может текст совпасть со служебным форматированием (и неправильно обработает тогда), пока простого способа обойти не придумал -> например, b1 - это служебное поле on state bold.


Код:
[Выделить все]
// Windows
using System;
using System.Collections.Generic;
using System.Text;

// AutoCAD
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

namespace ChangeMTextWithSaveFormat
{
    public class CommandsClass
    {
        
        /// <summary>
        /// Содержимое мультитекста со всем форматированием
        /// </summary>
        private string _ContentMText;

        /// <summary>
        /// Список длин вставок текста
        /// </summary>
        private List<int> _ListLenInsert = new List<int>();

        /// <summary>
        /// Текущая позиция в обрабатываемом тексте
        /// </summary>
        private int _CurrentPos;

        /// <summary>
        /// Список управляющих кодов
        /// </summary>
        private List<string> _ListCodes = new List<string>();



        /// <summary>
        /// Функция обратного вызова для получения фрагмента мультитекста
        /// </summary>
        /// <param name="aMFrag">Фрагмент мультитекста</param>
        /// <param name="aUD">Пользовательские данные</param>
        /// <returns></returns>
        private MTextFragmentCallbackStatus MTextCallback(MTextFragment aMFrag, object aUD)
        {
            // Получаем длину текста
            int lLenText = aMFrag.Text.Length;
            // Если есть текст
            if (lLenText > 0)
            {
                // Ищем текст в строке содержимого мультитекста
                int lPos = _ContentMText.IndexOf(aMFrag.Text + "}", _CurrentPos);
                if (lPos == -1) lPos = _ContentMText.IndexOf(aMFrag.Text, _CurrentPos);
                // Добавляем форматирование в список
                _ListCodes.Add(_ContentMText.Substring(_CurrentPos, lPos - _CurrentPos));
                // Добавляем количество символов для замены в список
                _ListLenInsert.Add(lLenText);
                // Корректируем текущую позицию
                _CurrentPos = lPos + lLenText;
            }
            // Командуем продолжать парсинг
            return MTextFragmentCallbackStatus.Continue;
        }


        
        /// <summary>
        /// Лисп-функция замены содержимого мультитекста с сохранением содержимого
        /// </summary>
        /// <param name="aArgs">Аргументы функции: Идентификатор мультитекста, 
        /// искомое значение для замены, новое значение</param>
        [LispFunction("ReplaceMTextExt")]
        public void ReplaceMTextExt(ResultBuffer aArgs)
        {
            // Очищаем список кодов
            _ListCodes.Clear();
            // Очищаем список длин вставок
            _ListLenInsert.Clear();
            // Ставим указатель на первый элемент форматированной строки
            _CurrentPos = 0;
            // Получаем текущий документ
            Document lAcadDoc = Application.DocumentManager.MdiActiveDocument;
            // Если задано нужное число аргументов
            if ((aArgs != null) && (aArgs.AsArray().Length == 3))
            {
                try
                {
                    // Получаем массив параметров функции
                    Array lArgArray = aArgs.AsArray();
                    // Преобразуем аргументы
                    ObjectId lTableId = (ObjectId)(((TypedValue)lArgArray.GetValue(0)).Value);
                    string lOldText = (string)(((TypedValue)lArgArray.GetValue(1)).Value);
                    string lNewText = (string)(((TypedValue)lArgArray.GetValue(2)).Value);
                    // Открываем транзакцию
                    using (Transaction lAcadTrans = lAcadDoc.TransactionManager.StartTransaction())
                    {
                        DBObject lDBObject = lAcadTrans.GetObject(lTableId, OpenMode.ForWrite);
                        MText lMText = lDBObject as MText;
                        if (lMText != null)
                        {
                            // Сохраняем содержимое мультитекста вместе с форматированием
                            _ContentMText = lMText.Contents;
                            // Получаем и сохраняем новое значение текста после замены
                            string lNewMTextValue = lMText.Text.Replace(lOldText, lNewText);
                            // Получаем длину нового значения текста
                            int lLenNewValue = lNewMTextValue.Length;
                            // Если новая строка не пустая
                            if (lLenNewValue > 0)
                            {
                                // Если мультитекст содержит форматирование
                                if (_ContentMText.Contains(@"{\"))
                                {
                                    // Парсим содержимое мультитекста
                                    lMText.ExplodeFragments(new MTextFragmentCallback(MTextCallback));
                                    // Если новая строка больше старой
                                    if (lMText.Text.Length < lLenNewValue)
                                    {
                                        // Корректируем длину последней вставки
                                        _ListLenInsert[_ListCodes.Count - 1] += 
                                            lLenNewValue - lMText.Text.Length + 1;
                                    }
                                    // Собираем новое содержимое мультитекста с форматированием
                                    StringBuilder lNewContent = new StringBuilder();
                                    int lCurrentPos = 0;
                                    for (int i = 0; i < _ListCodes.Count; i++)
                                    {
                                        // Добавляем коды форматирования
                                        lNewContent.Append(_ListCodes[i]);
                                        // Если в строке достаточно символов для добавления
                                        if ((lCurrentPos + _ListLenInsert[i]) < lLenNewValue)
                                        {
                                            // Добавляем фрагмент строки с текущей позицией и длиной из списка 
                                            lNewContent.Append(
                                                lNewMTextValue.Substring(lCurrentPos, _ListLenInsert[i]));
                                        }
                                        else
                                        {
                                            // Если текущая позиция еще в пределах новой строки
                                            if (lCurrentPos < lLenNewValue)
                                            {
                                                // Копируем содержимое до конца строки
                                                lNewContent.Append(lNewMTextValue.Substring(lCurrentPos));
                                            }
                                            else
                                            {
                                                // Добавляем пустую строку
                                                lNewContent.Append(String.Empty);
                                            }
                                        }
                                        // Корректируем позицию
                                        lCurrentPos += _ListLenInsert[i];
                                    }
                                    // Сохраняем новый мультитекст
                                    lMText.Contents = lNewContent.ToString();
                                }
                                else
                                {
                                    // Если не содержит форматирования, то просто заменяем на новую строку
                                    lMText.Contents = lNewMTextValue;
                                }
                            }
                        }
                        else
                        {
                            // Выводим сообщение об несоответствии типа
                            lAcadDoc.Editor.WriteMessage("\nУказан не мультитекст!");
                        }
                        // Подтверждаем транзакцию
                        lAcadTrans.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    // Выводим сообщение об ошибке
                    lAcadDoc.Editor.WriteMessage("\nПроизошла ошибка: {0}", ex.Message);
                }
                finally
                {
                    // Очищаем список кодов
                    _ListCodes.Clear();
                    // Очищаем список длин вставок
                    _ListLenInsert.Clear();
                }
            }
            else
            {
                // Выводим сообщение об отсуствии аргументов
                lAcadDoc.Editor.WriteMessage("\nНе заданы параметры!");
            }
        }

    }
}


Использование
Код:
[Выделить все]
 (ReplaceMTextExt (car (entsel "Выберите мультитекст:")) "Значение для замены" "Новое значение")
upd: изменил код функции обратного вызова - - теперь не должна путать форматирование b1 с текстом b1 и т.п.

Последний раз редактировалось Сергей812, 16.12.2018 в 19:14. Причина: изменение кода функции обратного вызова
Сергей812 вне форума  
 
Непрочитано 18.12.2018, 14:03
#13
===AAA===


 
Регистрация: 15.08.2005
г. Норильск
Сообщений: 451


От это да...

Потестирую, обязательно сообщу результат.

Но уже после Нового Года, раньше не получится.

Всех с наступающим праздником!
__________________
Счастливо, Алексей!
===AAA=== вне форума  
 
Непрочитано 18.12.2018, 14:16
#14
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


===AAA===, там принцип - извлекаем через обратную функцию коды форматирования и длины самого текста каждого фрагмента - и сохраняем в отдельные списки. Потом заменяем в чистой строке без форматирования содержимое и собираем обратно. Т.е. коды форматирования не парсим (и на их структуру не заморачиваемся - ибо лень) и коды управляющих символов оставляем как есть.
Сергей812 вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Замена символов в строке

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
LISP. Замена текстового стиля VVA Готовые программы 305 26.03.2024 12:03
Как вывести меню команды в командной строке? (пояснения внутри) Booka1a AutoCAD 16 02.02.2018 17:55
Является ли замена плит покрытия капремонтом или реконструкцией sergkuz Прочее. Архитектура и строительство 44 07.04.2017 18:29
Поиск и замена спец символов в многострочном тексте Psyakrev AutoCAD 5 25.01.2011 12:49
Поиск и замена символов в текстовой строке DEMOGOG Программирование 10 09.09.2009 11:46