求从字符串中提取一个有规则的子字符串的高效率算法? 急 ( 积分: 50 )

  • 主题发起人 主题发起人 kaolasoft
  • 开始时间 开始时间
K

kaolasoft

Unregistered / Unconfirmed
GUEST, unregistred user!
请问如何从文本提取有一定规则的字串。
比如:
在下面文本中提取[AAA]****[BBB]****[CCC]格式的字串
秋当防燥,年年[AAA]111[BBB]324[CCC]如此。今年的润燥[AAA]45545[BBB]345[CCC]菜式有新意,雪梨[AAA]554[BBB]755[CCC]、木瓜等水果不再仅仅是生吃,也可以在餐桌上客串一[AAA]7675[BBB]1231[CCC]回主角;川贝、虫草等药材也不是只有炖汤里才出现,同样也能入菜下饭;还有冬瓜、西瓜等夏日圣品与秋季润燥[AAA]555[BBB]454[CCC]的食物结合,除燥的[AAA]977[BBB]211[CCC]同时还帮助暑热未消的同志解[AAA]r44[BBB]7777[CCC]把渴。秋季防燥食品主要有银耳、百合、芝麻、甘蔗、牛奶和蜂蜜,使用[AAA]2332[BBB]23[CCC]这些食物来烹调菜肴时,要注意针对肺、胃和肝肾等不同部位的燥症。同时饮茶、小食、炖汤、家常菜肴以及粥和酒等都可以作为润燥的着眼处。饭前饮用花旗参茶或食用雪梨一只,也是简便有效的防燥小法。
 
请问如何从文本提取有一定规则的字串。
比如:
在下面文本中提取[AAA]****[BBB]****[CCC]格式的字串
秋当防燥,年年[AAA]111[BBB]324[CCC]如此。今年的润燥[AAA]45545[BBB]345[CCC]菜式有新意,雪梨[AAA]554[BBB]755[CCC]、木瓜等水果不再仅仅是生吃,也可以在餐桌上客串一[AAA]7675[BBB]1231[CCC]回主角;川贝、虫草等药材也不是只有炖汤里才出现,同样也能入菜下饭;还有冬瓜、西瓜等夏日圣品与秋季润燥[AAA]555[BBB]454[CCC]的食物结合,除燥的[AAA]977[BBB]211[CCC]同时还帮助暑热未消的同志解[AAA]r44[BBB]7777[CCC]把渴。秋季防燥食品主要有银耳、百合、芝麻、甘蔗、牛奶和蜂蜜,使用[AAA]2332[BBB]23[CCC]这些食物来烹调菜肴时,要注意针对肺、胃和肝肾等不同部位的燥症。同时饮茶、小食、炖汤、家常菜肴以及粥和酒等都可以作为润燥的着眼处。饭前饮用花旗参茶或食用雪梨一只,也是简便有效的防燥小法。
 
procedure GetBodyStr(const str, head, tail: string
var sl: TStringList);
var
s: string;
nHeadLen, nTailLen, nHead, nTail: Word;
begin
s := str;
nHeadLen := Length(head);
nTailLen := Length(tail);
nHead := 1;
nTail := nHead;
while (nHead > 0) and (nTail > 0) do
begin
nHead := Pos(head, s);
Delete(s, 1, nHead + nHeadLen - 1);
nTail := Pos(tail, s);
if nTail > 1 then
sl.Add(Copy(s, 1, nTail - 1));
Delete(s, 1, nTail + nTailLen);
end;
end;
这样用(你的字符串是在文件里还是别的地方我不清楚,你自己处理吧):
var
s: string;
sl: TStringList;
begin
s := 'gert4564wwttt23ee2yyyiiretertwwttt232eeyyyiitewtwwttt2hh32yyyiie';
sl := TStringList.Create;
GetBodyStr(s, 'wwttt', 'yyyii', sl);
end;
 
取得串长再用pos取得“]”的位置再取得“[”的位置用copy截取串,循环。
 
谢谢vvyang 的帮助
这个算法还不是很完善,靠要提取字串的头跟尾来提取,会出错,若中间变动的文本也有这样的字串就不行了。如:wwttt23_wwttt_2yyyii
另外要提取的字串可能不只这样,比如:rrr***yyy***uuu
 
to :newsmile
用这个是想加粗文本,怎么大富翁论坛不支持呢,请版主解决一下
 
不只用正则表达式能不能实现,请高手提点一下
 
delete+Copy+pos
 
请高手指导
 
Uses
StrUtils;

function StepList(First, Mid, Last, S: String): TStrings;
var
FPos, NewPos, L1, L2, L3: integer;
begin
L1 := length(First);
L2 := length(Mid);
L3 := length(Last);
Result := TStringList.Create;
FPos := 1;
repeat
FPos := PosEx(First, S, FPos);
if FPos = 0 then Exit;

FPos := FPos + L1;
NewPos := PosEx(Mid, S, FPos);
if NewPos = 0 then Exit;
Result.Add(copy(S, FPos, NewPos - FPos));

FPos := NewPos + L2;
NewPos := PosEx(Last, s, FPos);
if NewPos = 0 then Exit;
Result.Add(copy(S, FPos, NewPos - FPos));

FPos := NewPos + L3;
until False;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
SFirst = '[AAA]';
SMid = '[BBB]';
SLast = '[CCC]';
var
StrLst: TStrings;
begin
StrLst := StepList(SFirst, SMid, SLast, Edit1.Text);
try
Memo1.Lines.Assign(StrLst);
finally
StrLst.Free;
end;
end;
 
谢谢jeffrey_s
这样做法效率有点低
而且通用性不是很好
要查找的字串再复杂点 就不好办了
比如:就这样简单的增加 [AAA]111[BBB]324[CCC]777[EEE]434[EEE]
 
如果你觉得没效率我也没办法,我觉得还可以。。

至于你说的通用性,我只是觉得你的数据和例子里说明的特征不明显。
比如[AAA]111[BBB]324[CCC]777[EEE]434[EEE]3366[AAA]111[BBB]324[CCC]777[EEE]434[EEE]
那么[EEE]3366[AAA]中的数据要还是不要?题目并没给出相应的约束条件。
 
后退
顶部