AWK 또는 SED를 사용하여 다른 파일에서 변수를 제거하여 파일의 줄 삭제

AWK 또는 SED를 사용하여 다른 파일에서 변수를 제거하여 파일의 줄 삭제

data.txt파일의 두 번째 열 매개변수 중 하나가 포함된 모든 줄을 삭제하고 싶습니다 keys.txt.

  • keys.txt
    2 aa
    2 bb
    2 cc
    2 dd
    
  • data.txt
    1 aa It is great
    1 aa I want to delete this line
    1 kk Really ?
    1 bb Yes, I think so.
    1 bb Why ?
    1 kk Because I don't like the current situation
    1 ll I want to change
    1 cc Indeed it's a need
    1 cc Sorry
    1 zz Ok !
    
  • 원하는 출력
    1 kk Really ?
    1 kk Because I don't like the current situation
    1 ll I want to change
    1 zz Ok !
    

다음 프로그램을 사용해 보았습니다 awk.

awk '
    NR == FNR {pattern[$0]; next}
    {
        for (var in pattern) {
            if ($0 ~ var) {
                getline
                next
            }
        }
        print >> GoodFile.txt
    }
' keys.txt

답변1

당신은 꽤 가까웠지만 몇 가지 작은 점이 빠졌습니다.

  • data.txt이를 호출에 매개변수로 추가 해야 합니다 awk. 그렇지 않으면 파일이 처리되지 않습니다.
  • 현재 전체 행을 keys.txt삭제 데이터베이스에 등록하고 있으므로 두 번째 필드( $2대신 $0)로 제한해야 합니다.
  • if ($0 ~ var)행을 제외해야 하는지 확인하는 데 사용됩니다 . data.txt여기에서도 행의 두 번째 필드만 비교해야 하며, ==키에 정규식 관련 문자가 포함될 수 있는 경우를 방지하려면 정규식 일치 대신 완전 일치( )를 사용해야 합니다.
  • 에서 인쇄 awk하지만 꼭 그럴 필요는 없습니다. 대신 출력을 리디렉션할 수 있습니다.

따라서 약간 수정하면 다음과 같습니다.

awk 'NR==FNR{pattern[$2];next} !($2 in pattern)' keys.txt data.txt > GoodFile.txt

keys.txt이는 배열의 각 행의 두 번째 열을 등록 pattern하지만 파일에 대해 다른 작업은 수행하지 않습니다. 왜냐하면, data.txt각 라인에 대해 조건이 평가되는 지점에 도달할 것이기 때문입니다 . !($2 in pattern)조건이 "true"로 평가되는 경우(즉, 행의 두 번째 열이아니요배열의 인덱스에서 pattern) 현재 행이 인쇄됩니다.

답변2

스크립트의 첫 번째 질문은 다음과 같습니다.

NR == FNR {pattern[$0]; next}

전체 행을 배열의 키로 사용 pattern하지만 두 번째 필드만 필요합니다. 와 를 둘 다 사용할 필요 next는 없고 그냥 다음 줄로 넘어가면 getline됩니다 . next또한 두 번째 파일을 입력으로 전달하는 것을 잊었습니다. 마지막으로 파일 이름은 변수가 아닌 문자열이므로 따옴표로 묶어야 합니다. 이 두 가지 오류를 수정하면 다음이 발생합니다.

awk '
    NR == FNR {pattern[$2]; next}
    {
        for (var in pattern) {
            if ($0 ~ var) {
                getline
                next
            }
        }
        print >> "GoodFile.txt"
    }
' keys.txt data.txt

지금 당신은틀림없이거기서 그걸 원하세요 >>? 이는 awk파일에 이미 있는 항목(예: 이전 실행의 출력)을 덮어쓰지 않음을 의미합니다. 단일 실행의 출력을 덮어쓰지 않으 >>려면 필요하지 않습니다 . 이는 이전 실행의 데이터를 유지하려는 경우 에만 필요하지만 그렇지 않을 것 같습니다.awk>>>

또한 데이터를 기반으로 실제로 전체 행을 확인하고 싶지는 않습니다. data.txt두 번째 필드가 의 두 번째 필드와 동일한 행만 건너뛰려고 합니다 keys.txt. 그렇다면 특히 대용량 파일의 경우 더 효율적입니다.

awk '
    NR == FNR {pattern[$2]; next}
    {
        if ($2 in pattern) {
            next
        }
        print > "GoodFile.txt"
    }
' keys.txt data.txt

또는 동등하지만 더 간결하게 말하면 다음과 같습니다.

awk '
    NR == FNR {pattern[$2]; next}
    {
        if (!($2 in pattern) {
            print > "GoodFile.txt"
        }
    }
' keys.txt data.txt

답변3

GNU sed확장 정규식 모드 켜기 -E, 자동 인쇄 모드 공백 끄기-n

$ sed -En '
    /^\S+\s+(\S+)$/{
      s//\1/;H;d
    }
    G
    /^\S+\s+(\S+)\s.*\n\1(\n|$)/!P
' keys.txt data.txt

키 파일에 두 개의 필드가 있고 데이터 파일에 두 개 이상의 필드가 있다고 가정합니다.

첫 번째 단계에서는 key.txt 파일의 두 번째 필드를 보류 상태로 저장합니다. 그런 다음 data.txt 파일을 읽는 동안 data.txt 파일의 현재 레코드에 키를 추가하고 데이터의 두 번째 필드가 키의 어느 위치에서나 볼 수 있는지 비교합니다. 발견되지 않은 경우에만 데이터를 인쇄합니다.

관련 정보