여러 행에서 데이터 필드 추출

여러 행에서 데이터 필드 추출

텍스트를 한 형식에서 다른 형식으로 변환해야 하는 경우가 종종 있습니다. 일반적인 상황은 일부 정보가 포함된 로그 파일이 있고 해당 정보의 하위 집합을 찾아 매우 구체적인 방식으로 형식을 지정하려는 경우입니다.


이제 모든 "레코드"가 같은 줄에 있으면 작업이 비교적 쉽습니다.

  • grep선택적으로 관심 있는 행만 일치시키는 데 사용할 수 있습니다 .
  • sed관심 필드를 일치시키고, 캡처하고, 필요에 따라 형식화된 결과를 출력하는 데 사용됩니다 .

유일한 작은 문제는모두행이므로 sed해당 행은 폐기되고 원하는 출력만 인쇄됩니다. 하지만 그다지 어렵지는 않습니다.

필드 캡처 문제가 충분히 간단하다면 cut충분할 수도 있고 아마도 awk.


이제 실제 질문은 다음과 같습니다. 내가 원하는 필드가 여러 행에 걸쳐 있으면 어떻게 되나요?

예를 들어 어떤 사람이 있다고 가정해보자.

stat * >LOG.TXT

좋습니다. 이제 우리 LOG.TXT가 원하는 모든 정보가 포함된 파일이 생겼습니다. 하지만 다음과 같습니다.

  File: 'src.7z'
  Size: 269430          Blocks: 528        IO Block: 4096   regular file
Device: 801h/2049d      Inode: 799155      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2020-07-02 09:01:09.269292914 +0100
Modify: 2020-07-02 09:00:53.237293629 +0100
Change: 2020-07-02 09:00:53.237293629 +0100
 Birth: -

아마도 우리는 좀 더 비슷하게 보이는 것을 생성하고 싶을 수도 있습니다.

VerifyFile("src.7z", 269430, 0644);

지금,올바른 방법이를 위한 첫 번째 단계는 stat이런 방식으로 출력을 요구하는 것입니다! 일반적으로 말하자면,언제나사실 이후에 프랑켄슈타인 텍스트를 작성하려고 시도하는 것보다 소스 프로그램에서 시작하려는 형식을 생성하도록 하는 것이 더 좋습니다. 안타깝게도 인생이 항상 그렇게 단순하지는 않습니다. 로그 파일이 있고 연결 이벤트와 연결 끊김 이벤트를 연결하고 싶거나, 파일 목록이 있고 각 .c파일을 일치하는 .o파일과 연결하고 싶을 수도 있습니다. 이유가 무엇이든 결국에는 텍스트 수정 작업에 직면하게 됩니다.

그렇다면 이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 여러 개별 행에서 필드를 수집하여 동일한 행에 병합하면서도 레코드를 별도로 유지하려면 어떻게 해야 합니까? (즉, 넣지 마세요.모든 것거대한 줄에는 오직동일한기록. )

이러한 유형의 작업을 수행하는 일반적인 방법은 없습니다. 몇 가지 생각:

  • grep정규식과 일치하는 부분만 추출을 사용하여 원하는 필드를 추출 할 수 있습니다 . 그런데 추출할 방법이 없네요모두흥미로운 필드를 여러 번 실행하지 않으면 grep필드 간의 상대적 순서가 깨질 수 있습니다.
  • sed일치하는 비트만 추출하기가 더 어려워지지만 필드를 동일한 상대적 순서로 유지할 수 있습니다. 이제 어떻게든 같은 줄에 필드를 수집해야 합니다.
  • awk필드와 레코드의 개념이 있습니다. 나믿다정규식 일치를 수행할 수 있습니다. (정말 모르겠어요 awk.) 아마도 그게 이 문제를 해결하는 방법이 아닐까요? 꽤 복잡해 보이지만.
  • 파이썬으로 뭔가를 할 수 있나요? 일반적으로 설치된 것으로 보입니다. 정규식 기능이 있는지 모르겠습니다.

보통 나는 다음과 같은 것을 생각해냅니다.일하다, 그러나 읽기 쉽거나 유지 관리가 쉽지 않았습니다. 더 쉬운 방법이 있었으면 좋겠어요.

답변1

둘 다 여기에 awk적합합니다 python. 둘 다 연관 배열(또는 사전)을 지원하고 둘 다 정규 표현식이 내장되어 있습니다.

아마도 이를 처리하는 몇 가지 일반적인 방법이 있을 수 있지만 저는 사용할 수 있는 실제 입력/출력 예제를 기반으로 최적화하는 경향이 있습니다. 이것이 stat해결된 문제 입니다 awk.

$ cat kv.awk 
/File:/ {
    f = $2
}

/Size:/ {
    info[f] = $2
}

/Access.*Uid/ {
    gsub(/\(|\/.*/, "", $2)
    info[f] = info[f] OFS $2
}

END {
    for (k in info) {
        print "VerifyFile(\"" k "\"", info[k] ");"
    }
}

파일 이름은 다음과 같이 사용됩니다.열쇠관련된 모든 것을 모아보세요. 마지막으로 필요한 모든 형식으로 결과를 표시할 수 있습니다. GNU awk다차원 배열도 지원됩니다.

실행 예시는 다음과 같습니다.

$ stat ip.txt test.txt > file.txt

$ awk -v OFS=', ' -f kv.awk file.txt
VerifyFile("'test.txt'", 254, 0664);
VerifyFile("'ip.txt'", 301, 0664);

공부하려면 awk추천합니다https://www.gnu.org/software/gawk/manual/gawk.html다른 구현에 대한 세부 사항이 다루어 GNU awk지고 언급됩니다.

관련 정보