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


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, 일부 같은 cut과 tr. 내가하는 방법은 다음과 같습니다.

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

 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.