我需要在特定分隔符后提取子字符串,但如果指定的分隔符位于其他两个标记之间,则应忽略它。
例如,拿这个测试字符串:
快速<“@ brown fox”>跳过懒狗。快速的@ 棕色狐狸 跳过懒狗
所需的输出是:
棕色狐狸跳过懒狗
这是因为第一个找到@分隔符在两个“”之间,因此应该被忽略,第二个@分隔符不在“”内部,因此之后的文本应该被提取。
我可以使用Pos
找到@ delimiter的起始位置,然后将文本提取到右侧,如下所示:
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
I: Integer;
begin
S := 'The quick <"@brown fox"> jumps over the lazy dog. The quick @brown fox jumps over the lazy dog';
I := Pos('@', S);
if I > 0 then
begin
ShowMessage(Copy(S, I, Length(S)));
end;
end;
然而,无论是否包含两个“”,它总是会找到第一个@分隔符。以上结果是:
@brown fox“&gt;跳过懒狗。快速的@ 棕色狐狸跳过 懒狗
所需的结果应该是:
棕色狐狸跳过懒狗
如果分隔符位于两个“”标记之间,如何在使用Pos
时更改代码以忽略@分隔符?我只想找到第一个@分界符,然后复制文本。
在找到第一个有效的@分隔符之后是否还有其他@分隔符也没关系,例如这也应该是有效的:
快速&lt;“@ brown fox”&gt;跳过懒狗。快速的@ 棕色狐狸 跳跃@ ov @ er lazy @ dog
仍应返回:
棕色狐狸跳过懒狗
因为我们只对第一个有效的@分隔符感兴趣,之后忽略其他任何内容并忽略两个“”标记之间的任何内容。
请注意,虽然我已经标记了Delphi,但我确实主要使用Lazarus,所以我需要帮助提出一个不使用魔术帮助的解决方案,如字符串助手等。
感谢。
答案 0 :(得分:1)
要查明@
是否不在"
个封闭标记内,请从头开始解析字符串。
如果在开始标记之后找到分隔符,但没有结束标记,则此例程也将提取结果。
function ExtractString(const s: String): String;
var
tagOpen: Boolean;
delimiterPos,i,j: Integer;
begin
tagOpen := false;
delimiterPos := 0;
Result := '';
for i := 1 to Length(s) do begin
if (s[i] = '"') then begin
tagOpen := not tagOpen;
delimiterPos := 0;
end
else begin
if (s[i] = '@') then begin
if (delimiterPos = 0) then
delimiterPos := i;
if not tagOpen then // Found answer
Break;
end;
end;
end;
// If there is no closing tag and a delimiter is found
// since the last opening tag, deliver a result.
if (delimiterPos > 0) then begin
// Finally extract the string and remove all `@` delimiters.
SetLength(Result,Length(s)-delimiterPos);
j := 0;
for i := 1 to Length(Result) do begin
Inc(delimiterPos);
if (s[delimiterPos] <> '@') then begin
Inc(j);
Result[j] := s[delimiterPos];
end;
end;
SetLength(Result,j);
end;
end;
答案 1 :(得分:0)
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
L, I: Integer;
take : Boolean;
begin
S := 'The quick <"@brown fox"> jumps over the lazy dog. The quick @brown fox jumps over the lazy dog';
L := Length(S);
I := Pos('@', S);
while I > 0 do
begin
take := True;
if I > 1 then take := S[I-1] <> '"';
if take then begin
if I < L then
ShowMessage(Copy(S, I + 1, L));
Break;
end;
S[I] := '_';
I := Pos('@', S);
end;
end;