Странный вывод при циклическом просмотре текста с помощью DBMS_OUTPUT - PullRequest
0 голосов
/ 04 сентября 2018

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

Вероятно, это не лучший способ сделать это, но это то, что я придумал;

DECLARE
P_output_record          VARCHAR2(1000) := 'Well, Prince, so Genoa and Lucca are now just family estates of the Buonapartes. But I warn you, if you dont tell me that this means war, if you still try to defend the infamies and horrors perpetrated by that Antichrist I really believe he is Antichrist';
v_message_length         INTEGER;
v_written_chars          INTEGER;
v_new_line               VARCHAR2(30);
v_chars_to_write         INTEGER;
BEGIN
dbms_output.enable();
v_message_length := LENGTH(P_output_record);
v_written_chars := 0;

   WHILE(v_written_chars < v_message_length)
   LOOP
      IF(v_written_chars + 28 > v_message_length) THEN
        v_chars_to_write := (v_message_length - v_written_chars);
        v_new_line := SUBSTR( P_output_record, v_written_chars, v_chars_to_write);
      ELSE
        v_new_line := SUBSTR( P_output_record,v_written_chars, 28);
        --get the index of the last space so words dont spill to new lines
        v_chars_to_write := INSTR(v_new_line,' ', -1);
      END IF;
      DBMS_OUTPUT.PUT_LINE( SUBSTR( P_output_record, v_written_chars, v_chars_to_write-1));
      v_written_chars := v_written_chars + v_chars_to_write; 
   END LOOP;
END;

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

Смотрите здесь, как есть пробел во второй строке.

Well, Prince, so Genoa and
 Lucca are now just family
estates of the Buonapartes.
But I warn you, if you dont
tell me that this means
war, if you still try to
defend the infamies and
horrors perpetrated by that
Antichrist I really believe
he is Antichri

P.S. Я знаю, что мне не хватает некоторых символов в конце последней строки, но это проблема в другой раз.

Ответы [ 4 ]

0 голосов
/ 04 сентября 2018

Скомбинируйте это просто для удовольствия, вы также можете сделать следующее (в котором используется максимум 80 символов на строку, но вы можете изменить на что хотите). Он также сжимает несколько пробелов в один пробел:

select listagg(val, ' ') within group (order by levl)
from (
    with t as (
      select 'Well, Prince, so Genoa and Lucca are now just family estates of the Buonapartes. But I warn you, if you dont tell me that this means war, if you still try to defend the infamies and horrors perpetrated by that Antichrist I really believe he is Antichrist' as str
      from dual )
    select levl, val, trunc(running_count/80)+1 as line
    from (
        select level as levl, regexp_substr(str,'[^ ]+',1,level) as val, sum(length(regexp_substr(str,'[^ ]+',1,level))) over (order by level) as running_count
        from t
        connect by regexp_substr(str,'[^ ]+',1,level) is not null
    )
)
group by line;

Выход:

Ну, принц, так что Генуя и Лукка теперь просто семейные владения Buonapartes. Но я предупреждаю вас, если вы не скажете мне, что это означает войну, если вы все еще пытаетесь защитить злодеяния и ужасы, совершенные что антихрист, я действительно верю, что он антихрист

0 голосов
/ 04 сентября 2018

Триммер будет работать в вашем случае:

set serveroutput on;
DECLARE
P_output_record          VARCHAR2(1000) := 'Well, Prince, so Genoa and Lucca are now just family estates of the Buonapartes. But I warn you, if you dont tell me that this means war, if you still try to defend the infamies and horrors perpetrated by that Antichrist I really believe he is Antichrist';
v_message_length         INTEGER;
v_written_chars          INTEGER;
v_new_line               VARCHAR2(30);
v_chars_to_write         INTEGER;
BEGIN
dbms_output.enable();
v_message_length := LENGTH(P_output_record);
v_written_chars := 0;

   WHILE(v_written_chars < v_message_length)
   LOOP
      IF(v_written_chars + 28 > v_message_length) THEN
        v_chars_to_write := (v_message_length - v_written_chars);
        v_new_line := SUBSTR( P_output_record, v_written_chars, v_chars_to_write);
      ELSE
        v_new_line := SUBSTR( P_output_record,v_written_chars, 28);
        --get the index of the last space so words dont spill to new lines
        v_chars_to_write := INSTR(v_new_line,' ', -1);
      END IF;
      --See this line****************Edited line*************
      DBMS_OUTPUT.PUT_LINE( trim(SUBSTR( P_output_record, v_written_chars, v_chars_to_write-1)));
      v_written_chars := v_written_chars + v_chars_to_write; 
   END LOOP;
END;

Надеюсь, это поможет.

0 голосов
/ 04 сентября 2018

Проблема в том, что вы используете v_written_chars для вычисления количества уже написанных символов и для создания подстроки оставшейся части.

В первой итерации v_written_chars = 0, v_chars_to_write = 27, поэтому, когда вы делаете

v_written_chars := v_written_chars + v_chars_to_write;

вы получите v_written_chars = 27.

На второй итерации вы создаете подстроку, начиная с 27-го символа, который является пробелом, получая строку с начальным пробелом.

Простой способ отредактировать ваш код может быть путем инициализации

v_written_chars = 1;

С этим редактированием результат будет:

Well, Prince, so Genoa and
Lucca are now just family
estates of the Buonapartes.
But I warn you, if you dont
tell me that this means
war, if you still try to
defend the infamies and
horrors perpetrated by that
Antichrist I really believe
he is Antichri

Что касается последней части строки, когда вы окажетесь в последней строке, вам не нужно вычислять количество символов для записи, но вы можете просто сделать:

v_new_line := SUBSTR( P_output_record, v_written_chars);

С изменениями ваш код становится:

...
BEGIN
dbms_output.enable();
v_message_length := LENGTH(P_output_record);
v_written_chars := 1;

   WHILE(v_written_chars < v_message_length)
   LOOP
      IF(v_written_chars + 28 > v_message_length) THEN
        v_new_line := SUBSTR( P_output_record, v_written_chars);
      ELSE
        v_new_line := SUBSTR( P_output_record,v_written_chars, 28);
        --get the index of the last space so words dont spill to new lines
        v_chars_to_write := INSTR(v_new_line,' ', -1);
      END IF;
      DBMS_OUTPUT.PUT_LINE( SUBSTR( P_output_record, v_written_chars, v_chars_to_write-1));
      v_written_chars := v_written_chars + v_chars_to_write; 
   END LOOP;
END;

и результат:

Well, Prince, so Genoa and
Lucca are now just family
estates of the Buonapartes.
But I warn you, if you dont
tell me that this means
war, if you still try to
defend the infamies and
horrors perpetrated by that
Antichrist I really believe
he is Antichrist
0 голосов
/ 04 сентября 2018

Добавить TRIM, здесь:

DBMS_OUTPUT.PUT_LINE( trim(SUBSTR( P_output_record, v_written_chars, v_chars_to_write-1)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...