선택적으로 데이터 추출

선택적으로 데이터 추출

txt 파일에 다음과 같은 데이터 덩어리가 있습니다.

Informatica(r) PMCMD, version [9.5.1 HotFix4], build [313.0217], SOLARIS 64-bit 
Copyright (c) Informatica Corporation 1994 - 2014   
All Rights Reserved. 

Invoked at Wed Dec 30 11:13:42 2015 

Connected to Integration Service: [TEST_Integration_Service].   
Integration Service status: [Running]   
Integration Service startup time: [Sun Dec 27 06:37:32 2015]  
Integration Service current time: [Wed Dec 30 11:13:42 2015]  
Folder: [ALS_DIM]  
Workflow: [wf_ld_als_dim] version [1].  
Workflow run status: [Scheduled]  
Workflow run error code: [0]  
Workflow run id [0].  
Schedule time: [Wed Dec 30 19:00:00 2015]  
Workflow run type: [Schedule]  
Run workflow as user: [Administrator]  
Run workflow with Impersonated OSProfile in domain: []  
Integration Service: [TEST_Integration_Service]  
Folder: [ALS_FACT]  
Workflow: [wf_s_m_ld_interchanges_detail_log] version [1].  
Workflow run status: [Scheduled]  
Workflow run error code: [0]  
Workflow run id [0].  
Schedule time: [Mon Jan 04 16:30:00 2016]  
Workflow run type: [Schedule]  
Run workflow as user: [Administrator]  
Run workflow with Impersonated OSProfile in domain: []  
Integration Service: [TEST_Integration_Service]  
Folder: [ALS_PRD]  
Workflow: [wf_maint_service_fields] version [1].  
Workflow run status: [Scheduled]  
Workflow run error code: [0]  
Workflow run id [0].  
Schedule time: [Thu Dec 31 07:10:00 2015]  
Workflow run type: [Schedule]  
Run workflow as user: [Administrator]  
Run workflow with Impersonated OSProfile in domain: []  
Integration Service: [TEST_Integration_Service]  
Number of scheduled workflows on this Integration Service: [3]  
Disconnecting from Integration Service  

반복될 때마다 폴더명, 워크플로우명, 워크플로우 실행 상태, 예약 시간, 통합 서비스 이름만 순서대로 추출되도록 데이터를 다른 텍스트 파일로 추출해야 합니다.

예를 들어:

Insert into <tablename> values('ALS_DIM', 'wf_ld_als_dim', 'Scheduled', 'Wed Dec 30 19:00:00 2015', 'TEST_Integration_Service')

이는 첫 번째 그룹 등에 대해 가져와야 합니다.

저는 주어진 3개의 데이터 세트에 특정한 스크립트를 개발했지만 이를 통해 스크립트가 원하는 수의 데이터 세트에 대해 실행될 수 있어야 합니다.

저는 쉘 스크립팅에 대해 매우 기초적인 지식을 갖고 있으므로 이에 대한 도움을 받는 것이 좋을 것입니다.

답변1

일방 sed통행...

sed -ne'/^Folder: *\[/!{'                                     \
         -e'/^Workflow\( run status\)\{0,1\}: *\[/!{'         \
              -e'/^Schedule time: *\[/!{'                     \
                   -e'/^Integration Service: *\[/!d'          \
    -e\} -e\} -e\} -e"s//'/"      -e"s/\].*/'/"  -e'H;x'      \
                   -e'/ .*\n.*/h' -e's///'       -e'x'        \ 
                   -e's//Insert into <tablename> values(&)/'  \
                   -e's/\n//'     -e's//, /gp'

Insert into <tablename> values('ALS_DIM', 'wf_ld_als_dim', 'Scheduled', 'Wed Dec 30 19:00:00 2015', 'TEST_Integration_Service')
Insert into <tablename> values('ALS_FACT', 'wf_s_m_ld_interchanges_detail_log', 'Scheduled', 'Mon Jan 04 16:30:00 2016', 'TEST_Integration_Service')
Insert into <tablename> values('ALS_PRD', 'wf_maint_service_fields', 'Scheduled', 'Thu Dec 31 07:10:00 2015', 'TEST_Integration_Service')

따라서 첫 번째 줄은 다음과 같은 허용 가능한 일치 항목을 무효화합니다.

if ! match ^Folder: *\[
then  if ! match ^Workflow: *\[ or ^Workflow run status: *\[
      then if !  match ^Schedule time: *\[
           then  if !  match ^Integration Service: *\[
                 then  delete
                 fi
           fi
      fi
fi

그러나 라인이 체인 중 하나와 일치하면 체인이 끊어지고 끝까지 이동할 수 없습니다. 이는 주어진 일치 행에 대해 테스트된 마지막 정규식이 닫는 대괄호까지 해당 행의 선두를 설명한다는 것을 의미합니다. sed스크립트 에서는 빈 주소를 사용하여 가장 최근에 컴파일된 정규식을 다시 참조할 수 있습니다 //. 나는 그것을 바꾸고 s//'/원하는 출력의 선행 따옴표 로 바꾸겠습니다 .'

남은 것은 원하는 모든 정보와 ]각 줄의 첫 번째 줄 뒤의 후행 컨텍스트뿐입니다. 그래서 각 줄의 원치 않는 꼬리도 s/\].*/'/후행 인용문으로 대체했습니다.'

이 시점에서 모든 선은 원하는 부분으로 제거되었지만 아직 연결되지 않았습니다. 이를 달성하기 위해 H행 주기를 유지하는 이전 공간을 사용했습니다 . 따라서 각 행의 복사본을 H이전 공간 에 추가하고 x보존 및 모드 버퍼를 변경한 / .*\n.*/다음<스페이스>그 다음에<줄 바꿈>- 날짜 표시줄 다음 예약된 줄에서만 발생합니다.

패턴이 발견되면 h이전 공간을 덮어쓰고 s///교체합니다 .모두패턴 공간(이 반복의 마지막 행이므로 다음 반복을 위해 비워 두십시오.). 여기에 빈 주소가 있으면 s///해당 주소와 일치하는 줄의 내용만 삭제됩니다.<스페이스> + <줄 바꿈>패턴 - 따라서 각 반복의 마지막 줄에서만 이러한 명령이 성공할 수 있습니다.

어쨌든, 나중에 x마지막으로 홀드 버퍼와 패턴 버퍼를 변경했으므로 이제 패턴 버퍼에는 이 반복에 대한 모든 일치 항목이 다음과 같이 구분되어 포함됩니다.<줄 바꿈>그렇지 않으면 가장 가까운 일치 항목과 0만 포함됩니다.<줄 바꿈>수치. 이것이 이 반복에 대한 마지막 일치 라인인 경우 이 지점의 보유 버퍼는 비어 있습니다. 그렇지 않으면 지금까지 일치하는 모든 라인을 포함하며 각 라인에는 선행 접두사가 붙습니다.<줄 바꿈>.

다음으로 동일한 정규식을 다시 인용하고 다음으로 바꾸려고했습니다.<스페이스> + <줄 바꿈>자신만의 패턴으로 포장된Insert into <tablename> values(그리고 후행).

s///마지막으로, 나는 선두를 교체하지 않을 것 입니다 .<줄 바꿈>마지막으로 일치하는 줄의 패턴 공간에 있고 나머지는 모두<줄 바꿈>쉼표 다음<스페이스>각. s///대체가 성공하면 그 결과가 표준 p출력으로 인쇄됩니다.

답변2

펄 방법:

$ perl -lne 'if(/^(Folder|Workflow|Workflow.*?status|Sched.*time|Integration Service):.*?\[([^][]+)/){++$k%5==0 ? print "$2"  : printf "%s,",$2}' file
ALS_DIM, wf_ld_als_dim, Scheduled, Wed Dec 30 19:00:00 2015, TEST_Integration_Service
ALS_FACT, wf_s_m_ld_interchanges_detail_log, Scheduled, Mon Jan 04 16:30:00 2016, TEST_Integration_Service
ALS_PRD, wf_maint_service_fields, Scheduled, Thu Dec 31 07:10:00 2015, TEST_Integration_Service

또는 더 간결하게 말하면:

$ perl -lne '
 if(/^                       ## Match the beginning of the line
     (                       ## 1st capturing group: $1
      Folder               | ## The various things we want to match
      Workflow             | 
      Workflow.*?status    |
      Sched.*time          |
      Integration\s*Service
      ):                     ## Only if they are followed by a :
      .*?\[
      (                      ## 2nd caprturing group: $2.
        [^][]+               ## The longest string of non-] or [
      )/x                    ## The x allows writing multiline regexes          
    )
{                            ## If this line matches...
    $k=$k+1;                   ## Increment the counter $k by one
    if($k%5==0){               ## If the current value of $k is a multiple of 5.
      print "$2"               ## Print the 2nd captured group and a newline.
    }                          ## The newline is automatically added by the -l. 

    else{
      printf "%s,",$2         ## For other lines, just print with no newline.
    }
}' file
ALS_DIM, wf_ld_als_dim, Scheduled, Wed Dec 30 19:00:00 2015, TEST_Integration_Service
ALS_FACT, wf_s_m_ld_interchanges_detail_log, Scheduled, Mon Jan 04 16:30:00 2016, TEST_Integration_Service
ALS_PRD, wf_maint_service_fields, Scheduled, Thu Dec 31 07:10:00 2015, TEST_Integration_Service

을 추가하려면 Insert ...간단한 패스를 전달하면 됩니다 sed.

$ perl -lne 'if(/^(Folder|Workflow|Workflow.*?status|Sched.*time|Integration Service):.*?\[([^][]+)/){++$k%5==0 ? print "$2"  : printf "%s,",$2}' file | 
    sed "s/^/Insert into <tablename> values('/; s/,/','/g; s/$/')/"
Insert into <tablename> values("ALS_DIM","wf_ld_als_dim","Scheduled","Wed Dec 30 19:00:00 2015","TEST_Integration_Service")
Insert into <tablename> values("ALS_FACT","wf_s_m_ld_interchanges_detail_log","Scheduled","Mon Jan 04 16:30:00 2016","TEST_Integration_Service")
Insert into <tablename> values("ALS_PRD","wf_maint_service_fields","Scheduled","Thu Dec 31 07:10:00 2015","TEST_Integration_Service")

sed세 가지 대체 연산자를 실행합니다 .

  • s/^/Insert into <tablename> values("/: ^줄의 시작 부분입니다. 따라서 s/^/foo/줄의 시작 부분에 삽입하십시오. foo여기에 삽입하고 있습니다 nsert into <tablename> values(".
  • s/,/','/g: ( s///g) 쉼표를 모두 로 바꿉니다 ','.
  • s/$/")/': $줄의 끝이므로 )"맨 끝에 추가됩니다.

관련 정보