파일에서 각 문자의 수를 계산하는 가장 빠른 방법은 무엇입니까?


121

파일에서 A 's T 's C 's G 's N 's 및 "-"문자 또는 필요한 경우 모든 문자를 세고 싶습니다.이를 수행하는 빠른 Unix 명령이 있습니까?


56
DNA 가닥에서 염기를 세고 있습니까?
Indrek

12
나는이 질문을 좋아하므로 동일한 문제를 해결하기 위해 많은 다른 접근법과 도구가 사용되었습니다.
Journeyman Geek

10
Heh, 이것은 경계 코드 골프입니다
Earlz

13
somone이 windows powershell 버전에 관심이 있다면 :[System.IO.File]::ReadAllText("C:\yourfile.txt").ToCharArray() | Group-Object $_ | Sort Count -Descending
Guillaume86

4
좋아, 나는 순수한 PS 방법을 발견했다고 생각한다 :Get-Content "C:\eula.3082.txt" | % { $_.ToCharArray() } | Group-Object | Sort Count -Descending
Guillaume86

답변:


136

실제 속도를 원한다면 :

echo 'int cache[256],x,y;char buf[4096],letters[]="tacgn-"; int main(){while((x=read(0,buf,sizeof buf))>0)for(y=0;y<x;y++)cache[(unsigned char)buf[y]]++;for(x=0;x<sizeof letters-1;x++)printf("%c: %d\n",letters[x],cache[letters[x]]);}' | gcc -w -xc -; ./a.out < file; rm a.out;

엄청나게 빠른 의사 1 라이너입니다.

간단한 테스트에 따르면 Core i7 CPU 870 @ 2.93GHz에서는 600MB / s 이상에 불과합니다.

$ du -h bigdna 
1.1G    bigdna

time ./a.out < bigdna 
t: 178977308
a: 178958411
c: 178958823
g: 178947772
n: 178959673
-: 178939837

real    0m1.718s
user    0m1.539s
sys     0m0.171s

정렬과 관련된 솔루션과 달리이 메모리는 일정한 (4K) 메모리에서 실행되므로 파일이 램보다 훨씬 큰 경우 매우 유용합니다.

그리고 약간의 팔꿈치 그리스로 0.7 초를 면도 할 수 있습니다.

echo 'int cache[256],x,buf[4096],*bp,*ep;char letters[]="tacgn-"; int main(){while((ep=buf+(read(0,buf,sizeof buf)/sizeof(int)))>buf)for(bp=buf;bp<ep;bp++){cache[(*bp)&0xff]++;cache[(*bp>>8)&0xff]++;cache[(*bp>>16)&0xff]++;cache[(*bp>>24)&0xff]++;}for(x=0;x<sizeof letters-1;x++)printf("%c: %d\n",letters[x],cache[letters[x]]);}' | gcc -O2 -xc -; ./a.out < file; rm a.out;

1.1GB / s 이상의 네트 :

real    0m0.943s
user    0m0.798s
sys     0m0.134s

비교를 위해, 나는이 페이지에서 어떤 속도 약속이있는 것처럼 보이는 다른 솔루션 중 일부를 테스트했습니다.

sed/ awk솔루션은 용감한 노력을하지만, 30 초 후에 사망했다. 이러한 간단한 정규식을 사용하면 이것이 sed (GNU sed 버전 4.2.1)의 버그 일 것으로 예상됩니다.

$ time sed 's/./&\n/g' bigdna | awk '!/^$/{a[$0]++}END{for (i in a)print i,a[i];}' 
sed: couldn't re-allocate memory

real    0m31.326s
user    0m21.696s
sys     0m2.111s

펄 방법도 유망한 것처럼 보였지만 7 분 동안 실행 한 후에 포기했습니다.

time perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c' < bigdna 
^C

real    7m44.161s
user    4m53.941s
sys     2m35.593s

1
+1 소수의 바이트가 아니라 데이터가 많을 때 적절한 솔루션을 제공합니다. 파일은 디스크 캐시에 있습니까?
Daniel Beck

2
깔끔한 것은 프로세싱에서 O (N)과 메모리에서 O (1)의 복잡성을 갖는다는 것입니다. 파이프는 일반적으로 처리시 O (N log N) (또는 심지어 O (N ^ 2)) 및 O (N)를 메모리에 갖습니다.
Martin Ueding

73
그러나 "명령 줄"의 정의를 상당히 확장하고 있습니다.
gerrit

11
질문의 요구 사항을 에픽 벤딩 -I 승인; p. superuser.com/a/486037/10165 <- 누군가가 벤치 마크를 실행하고,이 입니다 가장 빠른 옵션을 선택합니다.
Journeyman Geek

2
+1 올바른 장소에서 C를 잘 사용해 주셔서 감사합니다.
Jeff Ferland

119

grep -o foo.text -e A -e T -e C -e G -e N -e -|sort|uniq -c

하나의 라이너로 트릭을 수행합니다. 그래도 약간의 설명이 필요합니다.

grep -o foo.text -e A -e T -e C -e G -e N -e -foo.text 파일에서 문자 a와 g -를 검색하고 검색하려는 각 문자의 문자를 그립니다. 또한 한 문자를 한 줄에 인쇄합니다.

sort순서대로 정렬합니다. 이것은 다음 도구의 무대를 설정합니다

uniq -c모든 행의 중복 연속 발생 횟수를 계산합니다. 이 경우 정렬 된 문자 목록이 있으므로 첫 번째 단계에서 문자가 잘린 시점을 깔끔하게 계산합니다.

foo.txt에 문자열 GATTACA-이 포함되어 있으면 이 명령 세트에서 얻은 것입니다.

[geek@atremis ~]$ grep -o foo.text -e A -e T -e C -e G -e N -e -|sort|uniq -c
      1 -
      3 A
      1 C
      1 G
      2 T

8
블러디 유닉스 마법! : D
Pitto

27
파일에 CTAG 문자 만 있으면 정규 표현식 자체가 의미가 없습니다. grep -o. | 정렬 | uniq -c는 똑같이 잘 작동합니다.
sylvainulg

7
+1 grep을 25 년 동안 사용해 왔으며에 대해 몰랐습니다 -o.
LarsH

9
@JourneymanGeek : 이것의 문제점은 많은 데이터를 생성 한 다음 정렬하기 위해 전달된다는 것입니다. 프로그램이 각 문자를 구문 분석하는 것이 더 저렴합니다. O (N) 메모리 복잡성 답변 대신 O (1)에 대한 Dave의 답변을 참조하십시오.
Martin Ueding

2
@Pitto Native coreutils의 Windows 빌드는 널리 사용 가능합니다. Google에 문의하십시오
OrangeDog

46

@Journeyman의 답변에서 영감을 얻은이 제품을 사용해보십시오.

grep -o -E 'A|T|C|G|N|-' foo.txt | sort | uniq -c

핵심은 grep의 -o 옵션에 대해 알고있는 것 입니다. 이렇게하면 일치 항목이 분할되므로 각 출력 행은 일치하는 행의 전체 행이 아니라 패턴의 단일 인스턴스에 해당합니다. 이러한 지식이 주어지면 사용할 패턴과 선을 세는 방법 만 있으면됩니다. 정규 표현식을 사용하면 언급 한 문자와 일치하는 분리 패턴을 만들 수 있습니다.

A|T|C|G|N|-

이것은 "A 또는 T 또는 C 또는 G 또는 N 또는-일치"를 의미합니다. 이 설명서에는 사용할 수있는 다양한 정규식 구문이 설명되어 있습니다 .

이제 다음과 같은 출력이 나타납니다.

$ grep -o -E 'A|T|C|G|N|-' foo.txt 
A
T
C
G
N
-
-
A
A
N
N
N

마지막 단계는 sort | uniq -c@Journeyman의 답변에서 와 같이 모든 유사한 줄을 병합하고 계산하는 것입니다. 정렬은 다음과 같은 출력을 제공합니다.

$ grep -o -E 'A|T|C|G|N|-' foo.txt | sort
-
-
A
A
A
C
G
N
N
N
N
T

을 통해 파이프를 연결 uniq -c하면 결국 우리가 원하는 것과 유사합니다.

$ grep -o -E 'A|T|C|G|N|-' foo.txt | sort | uniq -c
      2 -
      3 A
      1 C
      1 G
      4 N
      1 T

부록 : 파일에서 A, C, G, N, T 및 문자 수를 합산하려면 grep 출력 wc -l대신을 통해 파이프 출력을 할 수 있습니다 sort | uniq -c. 이 접근 방식을 약간만 수정하여 계산할 수있는 많은 것들이 있습니다.


나는 coreutils와 정규식 인 rabbitholes을 탐구해야합니다. 이것은 내 것보다 다소 우아하다. p
Journeyman Geek

2
@JourneymanGeek : 정규 표현식을 남기는 것은 많은 일에 유용하기 때문에 문제가 될만한 가치가 있습니다. 제한 사항을 이해하고 XHTML 구문 분석 과 같은 정규 표현식 기능 범위를 벗어난 작업을 시도하여 힘을 남용하지 마십시오 .
crazy2be

20
grep -o '[ATCGN-]'은 여기서 좀 더 읽기 쉽습니다.
sylvainulg

14

파이썬을 사용하여 모든 문자를 세는 한 라이너 :

$ python -c "import collections, pprint; pprint.pprint(dict(collections.Counter(open('FILENAME_HERE', 'r').read())))"

... 다음과 같이 YAML 친화적 인 출력을 생성하십시오.

{'\n': 202,
 ' ': 2153,
 '!': 4,
 '"': 62,
 '#': 12,
 '%': 9,
 "'": 10,
 '(': 84,
 ')': 84,
 '*': 1,
 ',': 39,
 '-': 5,
 '.': 121,
 '/': 12,
 '0': 5,
 '1': 7,
 '2': 1,
 '3': 1,
 ':': 65,
 ';': 3,
 '<': 1,
 '=': 41,
 '>': 12,
 '@': 6,
 'A': 3,
 'B': 2,
 'C': 1,
 'D': 3,
 'E': 25}

파이썬이 코드의 명확성 측면에서 배쉬를 쉽게 이길 수있는 방법을 보는 것은 흥미 롭습니다.


11

전문가의 awk방법과 유사합니다 .

perl -e 'while (<>) {$c{$&}++ while /./g} print "$c{$_} $_\n" for keys %c'

10

몇 년 동안 UNIX를 사용한 후 다양한 필터링 및 계산 작업을 수행하기 위해 여러 소규모 작업을 연결하는 데 능숙합니다. 모두가 일부처럼 자신의 style--을 보유 awk하고 sed, 일부 같은 cuttr. 내가하는 방법은 다음과 같습니다.

특정 파일 이름을 처리하려면

 od -a FILENAME_HERE | cut -b 9- | tr " " \\n | egrep -v "^$" | sort | uniq -c

또는 필터로 :

 od -a | cut -b 9- | tr " " \\n | egrep -v "^$" | sort | uniq -c

다음과 같이 작동합니다.

  1. od -a 파일을 ASCII 문자로 분리합니다.
  2. cut -b 9-접두사 입력 od을 제거합니다 .
  3. tr " " \\n 문자 사이의 공백을 개행 문자로 변환하여 한 줄에 문자가 하나씩 있습니다.
  4. egrep -v "^$" 이것이 생성하는 여분의 빈 줄을 모두 제거합니다.
  5. sort 각 캐릭터의 인스턴스를 함께 수집합니다.
  6. uniq -c 각 줄의 반복 횟수를 계산합니다.

나는 "안녕 세상에!" 줄 바꿈이 이어지고 이것을 얻었습니다.

  1 ,
  1 !
  1 d
  1 e
  1 H
  3 l
  1 nl
  2 o
  1 r
  1 sp
  1 w

9

sed부분은 @Guru의 답변을 기반으로 uniq하며 David Schwartz의 솔루션과 비슷한을 사용하는 또 다른 접근법이 있습니다.

$ cat foo
aix
linux
bsd
foo
$ sed 's/\(.\)/\1\n/g' foo | sort | uniq -c
4 
1 a
1 b
1 d
1 f
2 i
1 l
1 n
2 o
1 s
1 u
2 x

1
사용 [[:alpha:]]하는 대신 .sed단지 일치하는 문자가 아닌 줄 바꿈합니다.
Claudius

1
[[:alpha:]]-질문에 언급 된 것과 같은 항목을 일치 시키려고하면 실패합니다.
Izkata

옳은. sed에 두 번째 표현식을 추가하여 먼저 다른 모든 것을 걸러 내고 원하는 문자와 명시 적으로 일치시키는 것이 sed -e 's/[^ATCGN-]//g' -e 's/\([ATCGN-]\)/\1\n/g' foo | sort | uniq -c좋습니다. 그러나 나는 거기에서 줄 바꿈을 제거하는 방법을 모른다 : \
Claudius

7

결합 grep하여 wc이를 수행 할 수 있습니다 .

grep -o 'character' file.txt | wc -w

grep지정된 파일에 대해 지정된 파일을 검색하고 -o옵션은 검색 텍스트가있는 각 줄을 인쇄하는 기본값이 아니라 실제 일치 항목 (예 : 찾고있는 문자) 만 인쇄하도록 지시합니다. 발견했다.

wc각 파일의 바이트 수, 단어 수 및 행 수를 인쇄하거나이 경우 grep명령 출력을 인쇄합니다 . 이 -w옵션은 단어를 세도록 지시하며, 각 단어는 검색 문자의 발생입니다. 물론, 검색 문자의 각 항목을 별도의 행에 인쇄하기 -l때문에 옵션 (행을 계산하는)도 작동 grep합니다.

한 번에 여러 문자에 대해이 작업을 수행하려면 문자를 배열에 넣고 반복하십시오.

chars=(A T C G N -)
for c in "${chars[@]}"; do echo -n $c ' ' && grep -o $c file.txt | wc -w; done

예 : string을 포함하는 파일의 TGC-GTCCNATGCGNNTCACANN-경우 출력은 다음과 같습니다.

A  3
T  4
C  6
G  4
N  5
-  2

자세한 내용은 man grep및을 참조하십시오 man wc.


이 방법의 단점은 사용자 Journeyman Geek가 아래 주석에서 언급 한 것처럼 grep각 문자마다 한 번씩 실행되어야 한다는 것 입니다. 파일 크기에 따라 눈에 띄는 성능 저하가 발생할 수 있습니다. 다른 한편으로,이 방법을 수행하면 어떤 코드가 검색되는지 신속하게 확인하고 나머지 코드와 별도의 줄에 있기 때문에 추가 / 제거하는 것이 조금 더 쉽습니다.


3
그들은 그들이 원하는 캐릭터마다 그것을 반복해야 할 것입니다 ... 나는 추가 할 것입니다. 더 우아한 솔루션이 있다고 맹세 할 수는 있지만 더 파고 들어야합니다. p
Journeyman Geek

@JourneymanGeek 좋은 지적입니다. 떠오르는 한 가지 접근 방식은 문자를 배열에 넣고 반복하는 것입니다. 내 게시물을 업데이트했습니다.
Indrek

너무 복잡한 IMO. grep -ea -et 등을 사용하십시오. 배열에 넣고 반복하면 문자 당 한 번 grep 사이클을 수행하지 않아도됩니까?
Journeyman Geek

@JourneymanGeek 아마 당신이 맞을 것입니다. uniq -c또한 멋진 형식의 출력을 얻는 더 좋은 방법처럼 보입니다. 나는 * nix 전문가가 아닙니다. 위의 내용은 제한된 지식과 일부 매뉴얼 페이지에서 정리 한 것입니다. :)
Indrek

마지막으로, 내 임무 중 하나는 약 5000 개의 주소록 항목을 정렬하는 것과 관련이 있었고, uniq로 인해 훨씬 ​​쉽게 만들었습니다.
Journeyman Geek

7

22hgp10a.txt의 시퀀스 라인을 사용하여 시스템의 grep과 awk 사이의 타이밍 차이는 awk를 사용하는 길을 만듭니다 ...

[편집] : Dave의 컴파일 된 솔루션을 본 후 대소 문자를 구분하기 위해이 파일에서 ~ 0.1 초 안에 완료되었으므로 awk도 잊어 버렸습니다.

# A nice large sample file.
wget http://gutenberg.readingroo.ms/etext02/22hgp10a.txt

# Omit the regular text up to the start `>chr22` indicator.
sed -ie '1,/^>chr22/d' 22hgp10a.txt

sudo test # Just get sudo setup to not ask for password...

# ghostdog74 answered a question <linked below> about character frequency which
# gave me all case sensitive [ACGNTacgnt] counts in ~10 seconds.
sudo chrt -f 99 /usr/bin/time -f "%E elapsed, %c context switches" \
awk -vFS="" '{for(i=1;i<=NF;i++)w[$i]++}END{for(i in w) print i,w[i]}' 22hgp10a.txt

# The grep version given by Journeyman Geek took a whopping 3:41.47 minutes
# and yielded the case sensitive [ACGNT] counts.
sudo chrt -f 99 /usr/bin/time -f "%E elapsed, %c context switches" \
grep -o foo.text -e A -e T -e C -e G -e N -e -|sort|uniq -c

대소 문자를 구분하지 않는 고스트 독 버전이 ~ 14 초 안에 완료되었습니다.

sed는 이 질문에 대한 대답에 설명되어 있습니다.
벤치마킹은 이 질문에 대한 정답 입니다.
ghostdog74의 답변은 이 질문에 대한 것 입니다.


1
s/cache[letters[x]]/cache[letters[x]]+cache[toupper(letters[x])]속도에 영향을주지 않고 대소 문자를 구분하지 않도록 채굴 할 수 있습니다 .
Dave

6

적절한 구현은 정렬을 피한다고 생각합니다. 그러나 모든 것을 4 번 읽는 것이 좋지 않기 때문에 어떻게 든 4 개의 필터를 통과하는 스트림을 생성 할 수 있다고 생각합니다. 각 문자마다 필터링되고 스트림 길이도 계산됩니다.

time cat /dev/random | tr -d -C 'AGCTN\-' | head -c16M >dna.txt
real    0m5.797s
user    0m6.816s
sys     0m1.371s

$ time tr -d -C 'AGCTN\-' <dna.txt | tee >(wc -c >tmp0.txt) | tr -d 'A' | 
tee >(wc -c >tmp1.txt) | tr -d 'G' | tee >(wc -c >tmp2.txt) | tr -d 'C' | 
tee >(wc -c >tmp3.txt) | tr -d 'T' | tee >(wc -c >tmp4.txt) | tr -d 'N' | 
tee >(wc -c >tmp5.txt) | tr -d '\-' | wc -c >tmp6.txt && cat tmp[0-6].txt

real    0m0.742s
user    0m0.883s
sys     0m0.866s

16777216
13983005
11184107
8387205
5591177
2795114
0

그런 다음 누적 합계는 tmp [0-6] .txt에 있습니다. 작업은 계속 진행 중입니다.

이 방법에는 13 파이프 만 있으며 1Mb 미만의 메모리로 변환됩니다.
물론 내가 가장 좋아하는 솔루션은 다음과 같습니다.

time cat >f.c && gcc -O6 f.c && ./a.out
# then type your favourite c-program
real    0m42.130s

이것은 매우 잘 사용 tr됩니다.
adavid

4

나는 uniq나에 대해 알지 grep -o못했지만 @JourneymanGeek와 @ crazy2be에 대한 나의 의견이 그런지지를 받았기 때문에 아마도 그것을 자신의 성향으로 바꿔야 할 것입니다.

파일에 "좋은"문자 만 포함하고 있다는 것을 알고 있다면

grep . -o YourFile | sort | uniq -c

일부 문자 만 세고 다른 문자는 세지 않아야하는 경우 (예 : 구분자)

grep '[ACTGN-]' YourFile | sort | uniq -c

첫 번째는 정규식 와일드 카드를 사용하는데 ., 이는 단일 문자와 일치합니다. 즉 제외하고 두 번째는 어떤 특정한 순서로, '허용되는 문자 세트'를 사용 -(마지막 와야 A-C사이에 '모든 문자로 해석 A하고 C). 이 경우, 쉘이 단일 문자 파일을 점검하기 위해이를 확장하지 않으려 고합니다 (없으면 "일치하지 않음"오류가 발생 함).

"sort"는 또한 -unique 플래그를 가지고 있기 때문에 한 번만보고하지만, 중복을 계산하는 동반자 플래그 uniq는 없으므로 필수적입니다.


-백 슬래시로 이스케이프하면 마지막에 올 필요가 없습니다 '[A\-CTGN]'.
Indrek

2

바보 같은 것 :

tr -cd ATCGN- | iconv -f ascii -t ucs2 | tr '\0' '\n' | sort | uniq -c
  • tr( -d) 모든 문자 를 삭제하고 ( -c) ATCGN-
  • iconv 모든 바이트 뒤에 0 바이트를 추가하기 위해 ucs2로 변환 (UTF16은 2 바이트로 제한됨)
  • 다른 trNUL 문자를 NL로 변환합니다. 이제 모든 캐릭터는 자신의 라인에 있습니다
  • sort | uniq -c유니크 라인 을 계산

이는 비표준 (GNU) -ogrep 옵션의 대안입니다.


여기서 명령과 논리에 대해 간단히 설명해 주시겠습니까?
Andrew Lambert

2
time $( { tr -cd ACGTD- < dna.txt | dd | tr -d A | dd | tr -d C | dd | tr -d G |
dd | tr -d T | dd | tr -d D | dd | tr -d - | dd >/dev/null; } 2>tmp ) &&
grep byte < tmp | sort -r -g | awk '{ if ((s-$0)>=0) { print s-$0} s=$0 }'

출력 형식이 가장 좋지 않습니다 ...

real    0m0.176s
user    0m0.200s
sys     0m0.160s
2069046
2070218
2061086
2057418
2070062
2052266

작동 이론 :

  • $ ({command | command} 2> tmp) 는 스트림 의 stderr 을 임시 파일로 리디렉션 합니다.
  • dd는 stdin을 stdout으로 출력하고 stderr에 전달 된 바이트 수를 출력합니다.
  • tr -d는 한 번에 한 문자 씩 걸러냅니다.
  • grep 및 sort는 dd의 출력을 내림차순으로 필터링합니다.
  • awk는 차이를 계산합니다
  • sort는 dd 인스턴스의 종료 순서 불확실성을 처리하기 위해 사후 처리 단계 에서만 사용됩니다.

속도는 60MBps +


개선 : tmp를 제거합니까? '붙여 넣기'를 사용하여 관련된 문자를 인쇄 하시겠습니까?
Aki Suihkonen

1

샘플 파일 :

$ cat file
aix
unix
linux

명령:

$ sed 's/./&\n/g' file | awk '!/^$/{a[$0]++}END{for (i in a)print i,a[i];}'
u 2
i 3
x 3
l 1
n 2
a 1

명확성이 부족하고 설명없이 원 라이너를 게시하는 경우 -1입니다. AFAIK, 이것은 포크 폭탄
PPC

1

다른 몇 가지를 결합

chars='abcdefghijklmnopqrstuvwxyz-'
grep -o -i "[$chars]" foo|sort | uniq -c

| sort -nr빈도 순으로 결과를 보려면 추가 하십시오.


1

짧은 답변:

상황이 허용되는 경우, 낮은 문자 세트의 파일 크기를 문자가없는 파일 크기와 비교하여 오프셋을 얻고 바이트 수만 계산하십시오.

아, 그러나 얽힌 세부 사항 :

그것들은 모두 아스키 문자입니다. 1 바이트 당 물론 파일에는 OS 및 파일을 만든 앱에서 사용하는 다양한 항목에 추가 메타 데이터가 추가되어 있습니다. 대부분의 경우 메타 데이터에 관계없이 동일한 공간을 차지할 것으로 예상하지만 접근 방식을 처음 테스트 한 다음 걱정하지 않기 전에 오프셋이 일정한지 확인하면서 동일한 환경을 유지하려고합니다. 또 다른 문제 는 줄 바꿈에는 일반적으로 두 개의 ASCII 공백 문자가 포함되며 탭이나 공백은 각각 하나라는 것입니다. 이것이 확실하고 사전에 몇 명인지 알 수있는 방법이 없다면 지금은 그만 읽겠습니다.

많은 제약 조건처럼 보일지 모르지만 쉽게 설정할 수 있다면 볼 수있는 많은 것들이 있다면 (가장 DNA 일 가능성이 가장 높은) 가장 쉬운 방법입니다. 길이가 많은 파일을 확인하고 상수를 빼면 매번 grep을 실행하는 것보다 빠릅니다.

만약:

  • 이것들은 순수한 텍스트 파일의 간단한 깨지지 않은 문자열입니다
  • Scite와 같은 동일한 바닐라 비 형식 텍스트 편집기 (공백 / 반환을 확인하는 한 붙여 넣기는 가능함) 또는 누군가가 작성한 일부 기본 프로그램에 의해 생성 된 동일한 파일 형식입니다.

중요하지 않을 수도 있지만 먼저 테스트해야 할 두 가지

  • 파일 이름은 길이가 같습니다
  • 파일은 같은 디렉토리에 있습니다

다음을 수행하여 오프셋을 찾으십시오.

빈 파일을 사람이 쉽게 계산할 수있는 몇 개의 문자와 몇 개의 추가 문자가있는 파일과 비교하십시오. 다른 두 파일 모두에서 빈 파일을 빼면 문자 수와 일치하는 바이트 수를 얻을 수 있습니다. 파일 길이를 확인하고 빈 양을 뺍니다. 여러 줄 파일을 찾으려면 대부분의 편집자는 줄 바꿈에 두 개의 특수 1 바이트 문자를 첨부합니다. 하나는 Microsoft에서 무시하는 경향이 있지만 공백 문자는 최소한 grep해야합니다. grep으로 모든 작업을 수행 할 수도 있습니다.


1

하스켈 방식 :

import Data.Ord
import Data.List
import Control.Arrow

main :: IO ()
main = interact $
  show . sortBy (comparing fst) . map (length &&& head) . group . sort

다음과 같이 작동합니다.

112123123412345
=> sort
111112222333445
=> group
11111 2222 333 44 5
=> map (length &&& head)
(5 '1') (4 '2') (3 '3') (2 '4') (1,'5')
=> sortBy (comparing fst)
(1 '5') (2 '4') (3 '3') (4 '2') (5 '1')
=> one can add some pretty-printing here
...

컴파일 및 사용 :

$ ghc -O2 q.hs
[1 of 1] Compiling Main             ( q.hs, q.o )
Linking q ...
$ echo 112123123412345 | ./q
[(1,'\n'),(1,'5'),(2,'4'),(3,'3'),(4,'2'),(5,'1')]%       
$ cat path/to/file | ./q
...

거대한 파일에는 좋지 않을 수 있습니다.


1

빠른 펄 해킹 :

perl -nle 'while(/[ATCGN]/g){$a{$&}+=1};END{for(keys(%a)){print "$_:$a{$_}"}}'
  • -n: 입력 줄을 반복하지만 아무것도 인쇄하지 않습니다.
  • -l: 자동으로 줄 바꿈 제거 또는 추가
  • while: 현재 줄에서 요청 된 모든 기호를 반복합니다.
  • END: 마지막에 결과 인쇄
  • %a: 값이 저장되는 해시

전혀 나타나지 않는 문자는 결과에 포함되지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.