我正在编写一些代码来接受输入字符串,并以多行形式输出以满足特定的行长,我还需要它始终以新单词开始新行,以便单词在行与行之间不会重叠,从而很难阅读。
这可能不是最好的方法,但这是我想出的;
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我知道我在最后一行的末尾缺少一些字符,但这又是一个问题。
答案 0 :(得分:1)
问题在于您使用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
答案 1 :(得分:0)
在此处添加TRIM
DBMS_OUTPUT.PUT_LINE( trim(SUBSTR( P_output_record, v_written_chars, v_chars_to_write-1)));
答案 2 :(得分:0)
Trim适用于您的情况:
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;
希望这会有所帮助。
答案 3 :(得分:0)
将它们放在一起只是为了好玩,您还可以执行以下操作(每行最多使用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。但是我警告你,如果你不告诉我这意味着战争, 如果您仍要捍卫由...造成的家庭和恐怖 我真的相信他是敌基督者