Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / разбор строки по разделителю / 22 сообщений из 22, страница 1 из 1
13.06.2019, 16:20
    #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
13.06.2019, 16:26
    #39826235
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
evgen29как получить значение каждого поля, чтобы учесть экранирование двойными кавычками?

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

QuoteChar поставь нужный
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.06.2019, 16:31
    #39826244
antox
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
Раньше вроде как-то так делали - тексте листа через стринг реплэйс меняли ЗПТ на #13#10, если я не ошибаюсь
...
Рейтинг: 0 / 0
13.06.2019, 17:01
    #39826263
DarkMaster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
Заменить имена полей и = на CRLF, сложить в стринг лист. У каждой строки в списке - убрать последнию запятую и убрать пустые строки.
...
Рейтинг: 0 / 0
13.06.2019, 23:57
    #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
14.06.2019, 00:08
    #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
14.06.2019, 10:04
    #39826439
evgen29
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
Ghost Writer,
а можно если не трудно строку кода, как метод объекта capicom или cadescom, а не набор констант? Просто к чему этот набор констант привязан не совсем ясно.
...
Рейтинг: 0 / 0
14.06.2019, 10:28
    #39826453
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
Дарю . В Delphi 7 правда в таком виде не скомпилируется, но поменять record на object, либо вытащить методы из recorda, думаю труда не составит?
...
Рейтинг: 0 / 0
14.06.2019, 10:58
    #39826470
Василий 2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
А на кавычках внутри кавычек эта регулярка сломается ?
...
Рейтинг: 0 / 0
14.06.2019, 11:15
    #39826485
ПЕНСИОНЕРКА
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
Василий 2А на кавычках внутри кавычек эта регулярка сломается ?
в этом и проблема(разбила строку для наглядности)
--проблема адресе
--в подразделении и организации могут быть и кавычки и запятые

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

за 5-10 минут. обычный for - case str[i] со всеми ключевыми знаками обработки. а так же 1 - 2 флага, типа bool которые включают разделитель между ключом = значением. Второй же, обозначающий начало " и быстрый проглот строки до "
...
Рейтинг: 0 / 0
14.06.2019, 21:48
    #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
14.06.2019, 21:50
    #39826776
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
А, там запятые в адресе.

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


на
Код: pascal
1.
2.
  CutSubParam(Line,'STREET = "');
  Writeln(CutSubParam(Line,'",'));
...
Рейтинг: 0 / 0
14.06.2019, 23:18
    #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
14.06.2019, 23:27
    #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
14.06.2019, 23:37
    #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
14.06.2019, 23:39
    #39826788
Ghost Writer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
упс, кодировочка сбилась
...
Рейтинг: 0 / 0
14.06.2019, 23:40
    #39826789
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбор строки по разделителю
Ghost Writer,

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

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


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