Coldfusion - Как анализировать и сегментировать данные из файла электронной почты - PullRequest
3 голосов
/ 23 мая 2019

Я пытаюсь проанализировать файлы электронной почты, которые будут периодически приходить на наличие данных, содержащихся внутри. Мы планируем настроить cfmail для получения электронной почты внутри ящика внутри CF Admin, чтобы запускаться каждую минуту.

Данные в электронном письме состоят из имени, кодового имени, адреса, описания и т. Д. И будут иметь согласованные метки, поэтому мы думаем о выполнении цикла или функции поиска для каждого поля данных. Это было бы хорошим началом?

Вот пример данных электронной почты:

ИНЦИДЕНТ # 12345

ДОЛГОСРОЧНЫЙ SYS # C12345

ОТЧЕТНО: 08:39:34 20.05.19 Природа: FD NEED Адрес: 12345 N TEST LN Город: Тествилл

отвечающие единицы: T12

Перекрестки: пересечение: N Test LN & W TEST LN

Lat = 39,587453 Lon = -86,485021

Комментарии: Это тестовый пост. Пожалуйста, не обращайте внимания

Вот изображение того, как на самом деле выглядят данные:

enter image description here

Итак, мы хотели бы извлечь следующее:

  1. ИНЦИДЕНТ
  2. LONG TERM SYS #
  3. ВЫСТУПИЛ
  4. Природа
  5. Адрес
  6. Город
  7. отвечающие единицы
  8. Перекрестки
  9. Комментарии

Любые отзывы или предложения будут с благодарностью!

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Кто-то опубликовал это, но оно, очевидно, было удалено.Кто бы это ни был, я хочу ОЧЕНЬ поблагодарить вас за то, что он работал отлично !!!!

Вот функция:

   <!---CREATE FUNCTION [tvf-Str-Extract] (@String varchar(max),@Delimiter1   
varchar(100),@Delimiter2 varchar(100))
Returns Table 
As
Return (  

with   cte1(N)   as (Select 1 From (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))     
N(N)),
   cte2(N)   as (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By    
(Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A   
),
   cte3(N)   as (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t 
Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1),
   cte4(N,L) as (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-
 S.N,8000) From cte3 S)


 Select RetSeq = Row_Number() over (Order By N)
  ,RetPos = N
  ,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1) 

 From  ( Select *,RetVal = Substring(@String, N, L) From cte4 ) A

 Where charindex(@Delimiter2,RetVal)>1
 )

А вот код CF, который работал:

 <cfquery name="body" datasource="#Application.dsn#">
                    Declare @S varchar(max) ='
                    INCIDENT  12345

                    LONG TERM SYS C12345

                    REPORTED: 08:39:34 05/20/19 Nature: FD NEED Address: 12345 N TEST   
  LN City: Testville

                    Responding Units: T12

                    Cross Streets: Intersection of: N Test LN & W TEST LN

                    Lat= 39.587453 Lon= -86.485021

                    Comments: This is a test post. Please disregard
                    '

                    Select Incident = ltrim(rtrim(B.RetVal))
                          ,LongTerm = ltrim(rtrim(C.RetVal))
                          ,Reported = ltrim(rtrim(D.RetVal))
                          ,Nature   = ltrim(rtrim(E.RetVal))
                          ,Address  = ltrim(rtrim(F.RetVal))
                          ,City     = ltrim(rtrim(G.RetVal))
                          ,RespUnit = ltrim(rtrim(H.RetVal))
                          ,CrossStr = ltrim(rtrim(I.RetVal))
                          ,Comments = ltrim(rtrim(J.RetVal))
                     From (values (replace(replace(@S,char(10),''),char(13),' ')) )A(S)
                     Outer Apply [dbo].[tvf-Str-Extract](S,'INCIDENT'       ,'LONG 
 TERM'  ) B
                     Outer Apply [dbo].[tvf-Str-Extract](S,'LONG TERM SYS'   
 ,'REPORTED'   ) C
                     Outer Apply [dbo].[tvf-Str-Extract](S,'REPORTED:'        ,'Nature'     
 ) D
                     Outer Apply [dbo].[tvf-Str-Extract](S,'Nature:'          
  ,'Address'    ) E
                     Outer Apply [dbo].[tvf-Str-Extract](S,'Address:'         ,'City'       
  ) F
                     Outer Apply [dbo].[tvf-Str-Extract](S,'City:'            
  ,'Responding ') G
                     Outer Apply [dbo].[tvf-Str-Extract](S,'Responding Units:','Cross'      
   ) H
                     Outer Apply [dbo].[tvf-Str-Extract](S,'Cross Streets:'   ,'Lat'       
  ) I
                     Outer Apply [dbo].[tvf-Str-Extract](S+'|||','Comments:'  ,'|||'        
   ) J
                    </cfquery>
                    <cfoutput>
                    B. #body.Incident#<br>
                    C. #body.LongTerm#<br>
                    D. #body.Reported#<br>
0 голосов
/ 25 мая 2019

SQL обычно имеет ограниченные строковые функции, поэтому это не лучший инструмент для разбора.Если содержимое электронной почты всегда в этом точном формате, вы можете использовать либо обычные строковые функции, либо регулярные выражения для его анализа.Однако последний вариант более гибок.

Я подозреваю, что контент на самом деле содержит новые строки, что упрощает синтаксический анализ.Однако, если вы предпочитаете искать содержимое между двумя метками, регулярные выражения помогут вам.

Создайте массив имен меток (только).Цикл по массиву, захватывая пару меток: «текущий» и «следующий».Используйте два значения в регулярном выражении для извлечения текста между ними:

label &"\s*[##:=](.*?)"& nextLabel

/* Explanation: */
label        - First label name (example: "Incident")
\s*          - Zero or more spaces 
[##:=]       - Any of these characters: pound sign, colon or equal sign 
(.*?)        - Group of zero or more characters (non-greedy) 
nextLabel    - Next label (example: "Long Term Sys")

Используйте reFindNoCase () , чтобы получить сведения о позиции и длине сопоставляемого текста.Затем используйте эти значения вместе с mid () для извлечения текста.

Обратите внимание, что новые версии, такие как ColdFusion 2016+, автоматически извлекают текст под ключом с именем MATCH

Example of reFindNoCase result in CF 2018

Более новый синтаксис CF2016 + более приятный, но что-то вроде этого работает в CF10:

emailBody = "INCIDENT # 12345 ... etc.... ";
labelArray = ["Incident", "Long Term Sys", "Reported", ..., "Comments" ];

for (pos = 1; pos <= arrayLen(labelArray); pos++) {

    // get current and next label
    hasNext   = pos < arrayLen(labelArray);
    currLabel = labelArray[ pos ];
    nextLabel = (hasNext ? labelArray[ pos+1 ] : "$");

    // extract label and value
    matches   = reFindNoCase( currLabel &"\s*[##:=](.*?)"& nextLabel, emailBody, 1, true);
    if (arrayLen(matches.len) >= 2) {
        results[ currLabel ] = mid( emailBody, matches.pos[2], matches.len[2]);
    }   
}

writeDump( results );

Результаты:

Screenshot of parsed results

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...