powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / разбор строки по разделителю
22 сообщений из 22, страница 1 из 1
разбор строки по разделителю
    #39826230
evgen29
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте! Есть Certificate.SubjectName, который содержит строку, разделенную запятыми.
Код: pascal
1.
SN = Фамилия, G = Имя, T = Должность, Неструктурированное имя = Тестовый, STREET = "Тестовый адрес, улица, дом, квартира", CN = ТЕСТ, OU = Подразделение, O = ИП Тест, L = Истра, S = Московская, C = RU, E = test@test.ru, ИНН = 123456789012, ОГРН = 1234567890123



можно это конечно загнать в StringList и разбить по DelimitedText, но у меня delphi 7 такое не может(код на нем, переносить нельзя), потому как не учитывает двойные кавычки и поле STREET понимает после разбиения как 4 поля( в этом примере). Вопрос - как получить значение каждого поля, чтобы учесть экранирование двойными кавычками?
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826235
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen29как получить значение каждого поля, чтобы учесть экранирование двойными кавычками?

Простенький парсер на основе конечного автомата пишется за пару часов с нуля.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826243
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
13.06.2019 16:20, evgen29 пишет:
> можно это конечно загнать в StringList и разбить по DelimitedText, но у меня delphi 7 такое не может

QuoteChar поставь нужный
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826244
antox
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Раньше вроде как-то так делали - тексте листа через стринг реплэйс меняли ЗПТ на #13#10, если я не ошибаюсь
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826263
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заменить имена полей и = на CRLF, сложить в стринг лист. У каждой строки в списке - убрать последнию запятую и убрать пустые строки.
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826367
evgen29
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
сделал через регулярные выражения.
Пример с одной кнопкой и полем ввода
в поле ввода текст такой же как в начале
может кому пригодится.
ps: регулярку конечно надо будет поменять в дальнейшем, учесть нюансы типа О'Брайан и прочее.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, RegExpr;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetCurrentCertInfo(str: string): WideString;
const
  expr = '(([a-zA-Z0-9а-яА-ЯёЁ_]+\s*)+=\s*([''"].*[''"]\s*|[a-zA-Z0-9а-яА-ЯёЁ_@\.\s]*),?)+';
var
  HeaderColumns: TStringList;
  i: integer;
  strreplace,match: string;
  r: TRegExpr;
begin
  strreplace:='';
  r := TRegExpr.Create;
  try // ensure memory clean-up
    r.Expression := expr;
    if r.Exec(str) then
      repeat
        match:=r.Match[0];
        if match[length(match)]=',' then match:=copy(match,0,length(trim(match))-1);
        strreplace := strreplace+match+chr(13)+chr(10);
      until not r.ExecNext;
  finally r.Free;
  end;
  result:=strreplace;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
  str: string;
begin
    try
      SL := TStringList.Create;
      SL.Text := GetCurrentCertInfo(Edit1.Text);
      str := SL.Values['SN'];
      str := SL.Values['E'];
      str := SL.Values['T'];
    finally
      SL.Free;
    end;
end;

end.



исходник модуля прикреплен и доступен по ссылке на проект:
https://regex.sorokin.engineer/ru/latest/index.html
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826368
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen29Вопрос - как получить значение каждого поля, чтобы учесть экранирование двойными кавычками?получать SubjectName из сертификата сразу в нормальном виде, с разбиением по строкам и без лишних кавычек:
CertNameToStr + CERT_X500_NAME_STR or CERT_NAME_STR_CRLF_FLAG or CERT_NAME_STR_NO_QUOTING_FLAG
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826439
evgen29
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ghost Writer,
а можно если не трудно строку кода, как метод объекта capicom или cadescom, а не набор констант? Просто к чему этот набор констант привязан не совсем ясно.
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826453
delphinotes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дарю . В Delphi 7 правда в таком виде не скомпилируется, но поменять record на object, либо вытащить методы из recorda, думаю труда не составит?
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826470
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А на кавычках внутри кавычек эта регулярка сломается ?
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826485
Фотография ПЕНСИОНЕРКА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2А на кавычках внутри кавычек эта регулярка сломается ?
в этом и проблема(разбила строку для наглядности)
--проблема адресе
--в подразделении и организации могут быть и кавычки и запятые

авторSN = Фамилия, G = Имя, T = Должность,
Неструктурированное имя = Тестовый,
STREET = "Тестовый адрес, улица, дом, квартира",
CN = ТЕСТ, OU = Подразделение, O = ИП Тест, L = Истра, S = Московская,
C = RU, E = test@test.ru, ИНН = 123456789012, ОГРН = 1234567890123
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826593
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Надо смотреть, как представлены кавычки внутри кавычек.
Самый лучший вариант - в #2 - сделать самому.
Через stringlist тоже можно, если способ вложенности кавычек в исходных данных совпадает с тем, что он ожидает (удвоение, емнип). Если там, например, экранирование, то облом.
Можно еще поискать функцию/модуль чтения CSV, он должен такие случаи обрабатывать. Но опять же способ вложенности кавычек должен совпасть.
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826598
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТС патологически ленив.
Написать годную ф-цию, обрабатывающую все нюансы, можно за полчаса.
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826772
shonli95
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
L_argo,

за 5-10 минут. обычный for - case str[i] со всеми ключевыми знаками обработки. а так же 1 - 2 флага, типа bool которые включают разделитель между ключом = значением. Второй же, обозначающий начало " и быстрый проглот строки до "
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826775
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хватает за глаза для простого парсинга.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Function CutSubParam(var Text: String; Delimeter: String = ';'): String;
var
  p : integer;
begin
  p:=pos(Delimeter,Text);
  if p=0 then begin
    Result:=Text;
    Text:='';
  end else begin
    Result:=copy(Text,1,p-1);
    Text:=copy(Text,p+length(Delimeter),length(Text));
  end;
end;



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
program Project10;

{$APPTYPE CONSOLE}

{$R *.res}

Function CutSubParam(var Text: String; Delimeter: String = ';'): String;
var
  p : integer;
begin
  p:=pos(Delimeter,Text);
  if p=0 then begin
    Result:=Text;
    Text:='';
  end else begin
    Result:=copy(Text,1,p-1);
    Text:=copy(Text,p+length(Delimeter),length(Text));
  end;
end;

var
  Line : string = 'SN = Фамилия, G = Имя, T = Должность, Неструктурированное имя = Тестовый, STREET = "Тестовый адрес, улица, дом, квартира", CN = ТЕСТ, OU = Подразделение, O = ИП Тест,'+
                  ' L = Истра, S = Московская, C = RU, E = test@test.ru, ИНН = 123456789012, ОГРН = 1234567890123';
  s    : string;
begin
  CutSubParam(Line,'SN = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'G = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'T = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'Неструктурированное имя = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'STREET = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'CN = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'OU = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'O = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'L = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'S = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'C = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'E = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'ИНН = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'ОГРН = ');
  Writeln(CutSubParam(Line,','));

  Readln;
end.



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Фамилия
Имя
Должность
Тестовый
"Тестовый адрес
ТЕСТ
Подразделение
ИП Тест
Истра
Московская
RU
test@test.ru
123456789012
1234567890123
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826776
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, там запятые в адресе.

Меняем
Код: pascal
1.
2.
  CutSubParam(Line,'STREET = ');
  Writeln(CutSubParam(Line,','));


на
Код: pascal
1.
2.
  CutSubParam(Line,'STREET = "');
  Writeln(CutSubParam(Line,'",'));
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826785
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
evgen29а можно если не трудно строку кода, как метод объекта capicom или cadescom, а не набор констант? Просто к чему этот набор констант привязан не совсем ясно.CertNameToStr это функция CryptoApi. Не ожидал я, что используешь "capicom или cadescom".

Ну тогда примерно так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
procedure TForm1.Button1Click(Sender: TObject);
const
  Subject = 'SN = Фамилия, G = Имя, T = Должность, Неструктурированное имя = Тестовый, STREET = "Тестовый адрес, улица, дом, квартира", CN = ТЕСТ, OU = ' +
  'Подразделение, O = ИП Тест, L = Истра, S = Московская, C = RU, E = test@test.ru, ИНН = 123456789012, ОГРН = 1234567890123';
var
  S, Param, Value, Result: string;
  Position: Integer;
begin
  S := AnsiReverseString(Subject);

  Position := Pos('=', S);
  while Position > 0 do
  begin
    Value := Copy(S, 1, Position);
    Result := Result + Value;
    Delete(S, 1, Length(Value));

    Position := Pos(',', S);

    if Position > 0 then
    begin
      Param := Copy(S, 1, Position - 1);
      Result := Result + Param + #13#10;
      Delete(S, 1, Length(Param) + 1);
    end
    else begin
      Param := Copy(S, 1, Length(S));
      Result := Result + Param + #13#10;
      Delete(S, 1, Length(S));
    end;

    Position := Pos('=', S);
  end;

  ShowMessage(AnsiReverseString(Result));
end;

лишние пробелы сам...
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826786
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
  CutSubParam(Line,'SN = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'G = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'T = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'Неструктурированное имя = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'STREET = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'CN = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'OU = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'O = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'L = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'S = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'C = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'E = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'ИНН = ');
  Writeln(CutSubParam(Line,','));
  CutSubParam(Line,'ОГРН = ');
  Writeln(CutSubParam(Line,','));

Это не универсально. Набор атрибутов заранее может быть неизвестен, могут встретиться экзотические. А бывает, что атрибуты встречаются неоднократно, но с разными значениями. Например, на скриншоте OU встречается аж 4 раза (и L дважды). Данная функция всегда будет находить только первое.
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826787
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writerлишние пробелы сам...ну ладно

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
procedure TForm1.Button1Click(Sender: TObject);
const
  Subject = 'SN = Ôàìèëèÿ, G = Èìÿ, T = Äîëæíîñòü, Íåñòðóêòóðèðîâàííîå èìÿ = Òåñòîâûé, STREET = "Òåñòîâûé àäðåñ, óëèöà, äîì, êâàðòèðà", CN = ÒÅÑÒ, OU = ' +
  'Ïîäðàçäåëåíèå, O = ÈÏ Òåñò, L = Èñòðà, S = Ìîñêîâñêàÿ, C = RU, E = test@test.ru, ÈÍÍ = 123456789012, ÎÃÐÍ = 1234567890123';
var
  S, Param, Value, Result: string;
  Position: Integer;
begin
  S := AnsiReverseString(Subject);

  Position := Pos('=', S);
  while Position > 0 do
  begin
    Value := Copy(S, 1, Position - 1);
    Result := Result + Trim(Value) + '=';
    Delete(S, 1, Length(Value) + 1);

    Position := Pos(' ,', S);

    if Position > 0 then
    begin
      Param := Copy(S, 1, Position);
      Delete(S, 1, Length(Param) + 1);
    end
    else begin
      Param := Copy(S, 1, Length(S));
      Delete(S, 1, Length(S));
    end;

    Result := Result + Trim(Param) + #13#10;
    Position := Pos('=', S);
  end;

  ShowMessage(AnsiReverseString(Result));
end;
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826788
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
упс, кодировочка сбилась
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826789
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

А я и написал что эта фнкция удобна для простого парсинга.

Если там идиотский формат с дублированием ключей - фигли уж тут тогда, все одно специфический парсер нужен.
...
Рейтинг: 0 / 0
разбор строки по разделителю
    #39826790
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Причем тут можно и моей функцией обойтись, но придется контроли этого самого дублирования добавлять.
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / разбор строки по разделителю
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]