2014-10-13 2 views
1

내 작업을 해결할 수있는 모든 것이 sed/awk/grep /와 도움이 필요합니다. 큰 파일이있어서 여러 개의 연속 된 줄을 추출해야합니다. <DN>패턴 사이에 여러 줄 인쇄 (첫 번째 패턴은 고유하지 않음)

과 끝 패턴 : </GR>

사이에 몇 줄이 같은 :

sed -n '/\<DN\>/,/\<\/GR\>/p' 
:이 시도했습니다

<DN>234</DN> 
<DD>sdfsd</DD> 
<BR>456456</BR> 
<COL>6575675 sdfsd</COL> 

<RAC>456464</RAC> 
<GR>sdfsdfsFFFDd</GR> 

나는 패턴을 시작하게

및 기타 여러 항목 (awk 및 sed 사용). 괜찮아 작동하지만, 문제는 소스 파일, <DN>와 라인의 무리의 끝에 </GR>없이 시작하는 라인을 포함 할 수 있다는 것입니다 그리고 결국 또 다른 정상을 가진 부분을 시작합니다

<DN>234</DN> - unneded DN 
<AB>sdfsd</AB> 
<DC>456456</DC> 
<EF>6575675 sdfsd</EF> 
....really large piece of unwanted text here.... 

<DN>234</DN> 
<DD>sdfsd</DD> 
<BR>456456</BR> 
<COL>6575675 sdfsd</COL> 

<RAC>456464</RAC> 
<GR>sdfsdfsFFFDd</GR> 
<RAC>456464</RAC> 
<GR>sdfsdfsFFFDd</GR> 

<DN>을 포함하지 않고 </GR>을 포함하는 로그의 가비지 부분을 어떻게 무시할 수 있습니까?

그리고 다음, 나는 <DN> 시작하여 </GR>로 끝나는 단일 라인 파일로 </GR><DN>에서 여러 조각을 변환해야합니다. 도움이 될 것입니다. 붙어있어

답변

0

pcregrep 도구를 사용할 수 있습니다.

$ pcregrep -o -M '(?s)(?<=^|\s)<DN>(?:(?!<DN>).)*?</GR>(?=\n|$)' file 
<DN>234</DN> 
<DD>sdfsd</DD> 
<BR>456456</BR> 
<COL>6575675 sdfsd</COL> 

<RAC>456464</RAC> 
<GR>sdfsdfsFFFDd</GR> 
떠들썩한 파티와
+0

답장을 보내 주셔서 감사합니다. 불행히도 귀하의 제안은 실제 파일에서 작동하지 않았습니다. 어쩌면 시스템에서 바이너리 파일로 취급하기 때문에 grep 명령에 -a 옵션을 추가하여 작동하게해야합니다. 그러나 pcregrep에는 그러한 옵션이 없습니다. –

+0

정확한 파일 내용을 pastebin이나 질문에 게시 할 수 있습니까? –

+0

너무 큽니다, 두려워요. 수백 메가 바이트의 파일에는 내가 추출해야하는 몇 가지 귀중한 데이터 라인이 포함되어 있습니다. 그리고 프로덕션 시스템에서 왔으며 클라이언트 데이터가 들어 있습니다. –

1
awk ' 
# Lines that start with '<DN>' start our matching. 
/^<DN>/ { 
    # If we saw a start without a matching end throw everything we've saved away. 
    if (dn) { 
     d="" 
    } 
    # Mark being in a '<DN>' element. 
    dn=1 
    # Save the current line. 
    d=$0 
    next 
} 

# Lines that end with '</GR>$' end our matching (but only if we are currently in a match). 
dn && /<\/GR>$/ { 
    # We aren't in a <DN> element anymore. 
    dn=0 
    # Print out the lines we've saved and the current line. 
    printf "%s%s%s\n", d, OFS, $0 
    # Reset our saved contents. 
    d="" 
    next 
} 

# If we are in a <DN> element and have saved contents append the current line to the contents (separated by OFS). 
dn && d { 
    d=d OFS $0 
} 
' file 
+0

와우, 고마워. 정말 대단합니다.이 사용하는 방법을 모르겠다. 내가 스크립트를 복사해야합니까? 이렇게하면 아무 일도 일어나지 않습니다. 시스템을 몇 초 동안 실행하고 아무것도 인쇄합니다. 그러나 파일을 확인하면 일치하는 데이터가 포함되어 있습니다. 수동으로 또는 grep -a와 함께 –

+0

파일에 DOS 행 끝이 있습니까? grep ' $' '일치하는 행을 찾으시겠습니까?'grep '^ ''? –

+0

실제로 파일에는 줄 끝이 없습니다 (적어도 notepad ++에는 CRLF 또는 이와 유사한 내용이 전혀 표시되지 않습니다). 이진진이지만 다소 큰 텍스트와 이진 데이터가 혼합되어 있습니다. grep -a '^ '20140905.log는 많은 일치 항목을 찾습니다. grep ' $'20140905.log - 아니요 –

1
awk ' 
    /^<DN>/ { n = 1 } 

    n { lines[n++] = $0 } 

    n && /<\/GR>$/ { 
    for (i=1; i<n; i++) printf "%s", lines[i] 
    print "" 
    n = 0 
    } 
' file 
+0

감사합니다! 이제 나는 그것을 사용하는 방법에 대한 조언이 필요합니다 :) 스크립트로 복사하고 "파일"을 실제 파일 이름으로 변경하면 아무 일도 일어나지 않습니다. 시스템이 몇 초 동안 실행하고 아무것도 인쇄하지 않습니다. –

+0

두 awk 솔루션의 경우 명령 줄에 코드를 복사하여 복사 한 다음'file' 입력을'myFileInput.txt' (또는 이와 유사한 것)으로 적절하게 변경하면됩니다. (나는 메모장에 복사하고 파일 이름을 선택/복사/붙여 넣기 명령 줄에 수정). 더 나은 해결책은 이들 중 하나를 파일에 저장하고 awk -f solutionN.awk myInputFile.txt'를 호출하는 것입니다. 다른 해결책이 몇 가지 있지만 여기에 적합하지는 않습니다 .- 행운을 빈다. – shellter

1

:

fun() 
{ 
    local line output; 
    while IFS= read -r line; do 
     if [[ $line =~ ^'<DN>' ]]; then 
      output=$line; 
     else 
      if [[ -n $output ]]; then 
       output=$output$'\n'$line; 
       if [[ $line =~ '</GR>'$ ]]; then 
        echo "$output"; 
        output=; 
       fi; 
      fi; 
     fi; 
    done 
} 

fun <file 
2

이 당신 (GNU이 나오지도)을 위해 일 수 있습니다

sed -n '/<DN>/{h;b};x;/./G;x;/<\/GR/{x;/./p;z;x}' file 

사용 <DN> 사이 라인을 저장할 수있는 보류 영역 </GR>.

관련 문제