기록 유형별로 기록을 분할하고 예상치 못한 기록 유형을 보고합니다.

기록 유형별로 기록을 분할하고 예상치 못한 기록 유형을 보고합니다.

myfile.txt여러 레코드 유형이 포함된 레코드가 있습니다 .
레코드 유형은 다음과 같이 위치 27에 있으며 길이는 3자입니다.

12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456I47XXXXXXXXX
12345678901234567890123456I49XXXXXXXXX
12345678901234567890123456I50XXXXXXXXX
12345678901234567890123456W55XXXXXXXXX
12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456I47XXXXXXXXX
12345678901234567890123456Q11XXXXXXXXX
12345678901234567890123456R11XXXXXXXXX
12345678901234567890123456W55XXXXXXXXX
12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456I47XXXXXXXXX
12345678901234567890123456I49XXXXXXXXX
12345678901234567890123456I50XXXXXXXXX
12345678901234567890123456Q11XXXXXXXXX
12345678901234567890123456R11XXXXXXXXX
12345678901234567890123456W55XXXXXXXXX

다음과 같이 레코드 유형별로 분할하고 싶습니다.

grep -E '^.{26}(E20)' myfile.txt > E20.txt
grep -E '^.{26}(I47)' myfile.txt > I47.txt
grep -E '^.{26}(I49)' myfile.txt > I49.txt
grep -E '^.{26}(I50)' myfile.txt > I50.txt
grep -E '^.{26}(Q11)' myfile.txt > Q11.txt
grep -E '^.{26}(R11)' myfile.txt > R11.txt
grep -E '^.{26}(W55)' myfile.txt > W55.txt

그리고 다음과 같은 다른 일을 하세요

echo "Unexpected record type"

레코드 종류가 (E20, I47, I49, I50, Q11, R11, W55)가 아닌 경우.

예를 들어 E20.txt파일은 다음과 같습니다.

12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456E20XXXXXXXXX

등.

Linux에서 이를 수행하는 우아한 방법(스크립트)이 있습니까?

답변1

이것은 한 가지 awk방법입니다. 먼저 "양호한" 레코드가 한 줄에 하나씩 포함된 파일을 만듭니다.

$ cat goodRecs 
E20
I47
I49
I50
Q11
R11
W55

그 다음에:

gawk 'FNR==NR{good[$1]; next} 
     { 
        rec=substr($1,27,3); 
        if(rec in good){
            print > rec".txt"
        }
        else{
            print "Bad record: "rec
        }
    }' goodRecs myfile.txt 

답변2

awk 및 모든 종류를 사용하십시오.

$ cat tst.sh
#!/usr/bin/env bash

awk '
    BEGIN {
        split("E20 I47 I49 I50 Q11 R11 W55",tmp)
        for ( i in tmp ) {
            expected[tmp[i]]
        }
    }
    {
        type = substr($0,27,3)
        if ( type in expected ) {
            print type, NR, $0
        }
        else {
            printf "%s[%d]: Unexpected record type \"%s\"\n", FILENAME, FNR, type | "cat>&2"
        }
    }
' "${@:--}" |
sort -k1,1 -k2,2n |
awk '
    $1 != prev {
        close(out)
        out = $1 ".txt"
        prev = $1
    }
    { print $3 > out }
'

$ ./tst.sh myfile.txt

$ head [A-Z]*.txt
==> E20.txt <==
12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456E20XXXXXXXXX
12345678901234567890123456E20XXXXXXXXX

==> I47.txt <==
12345678901234567890123456I47XXXXXXXXX
12345678901234567890123456I47XXXXXXXXX
12345678901234567890123456I47XXXXXXXXX

==> I49.txt <==
12345678901234567890123456I49XXXXXXXXX
12345678901234567890123456I49XXXXXXXXX

==> I50.txt <==
12345678901234567890123456I50XXXXXXXXX
12345678901234567890123456I50XXXXXXXXX

==> Q11.txt <==
12345678901234567890123456Q11XXXXXXXXX
12345678901234567890123456Q11XXXXXXXXX

==> R11.txt <==
12345678901234567890123456R11XXXXXXXXX
12345678901234567890123456R11XXXXXXXXX

==> W55.txt <==
12345678901234567890123456W55XXXXXXXXX
12345678901234567890123456W55XXXXXXXXX
12345678901234567890123456W55XXXXXXXXX

위에서 사용된 것은DSU(장식/정렬/장식 취소) 관용구반복되는 키의 입력 순서를 유지하면서 스크립트를 매우 효율적이고 강력하며 이식 가능하게 만듭니다.

답변3

bash(또는 POSIX 쉘) 버전

#! /bin/sh

exec < "$1"

while read aline
do  key=${aline:26:3}
    case $key in 
    E20|I47|I49|I50|Q11|R11|W55)
        echo $aline >> $key.txt;;
    *)  echo "${0##/} Unexpected record '$key' encounterd" 1>&2;;
    esac
done

다음 명령을 실행하세요:

sh program-name input-file-name

/bin/sh를 사용할 수 없으면 bash를 사용하십시오.

관련 정보