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를 사용하십시오.