답변:
당신은 그것을 할 수 있습니다 sed
및 awk
:
$ sed 's/[^"]//g' dat | awk '{ print length }'
2
0
어디 dat
귀하의 예제 텍스트 (각 라인) 나오지도 삭제 모든 비입니다 "
문자와 awk
각 행의 크기의 인쇄 (즉 length
에 해당 length($0)
하는 경우, $0
현재 행을 나타낸다).
다른 캐릭터의 경우 sed 표현식 만 변경하면됩니다. 예를 들면 다음 (
과 같습니다.
's/[^(]//g'
업데이트 : sed
작업에 대한 일종의 과잉입니다- tr
충분합니다. 동등한 솔루션 tr
은 다음 과 같습니다.
$ tr -d -c '"\n' < dat | awk '{ print length; }'
문자 세트에 tr
없는 ( -c
보완을 의미하는) 모든 문자 를 삭제 한다는 의미입니다 "\n
.
tr
& wc
버전 보다 효율적이어야합니다 .
ß
(UTF 육각 : C3의 9F) (대신은 "
즉, 예상대로) 작동 tr
, sed
및 awk
- 우분투 10.04 시스템에서 문제없이 계산 / / 교체를 보완 않습니다.
tr
GNU 그럴 고전적인 유닉스 TR 포함이 단일 바이트 문자에서 작동 및 준수 유니 코드 ..에서 인용하지 위키 백과 TR (유닉스) ..이 조각을 시도해보십시오 echo "aā⧾c" | tr "ā⧾" b
... 우분투 10.04에 ... ß
단일 바이트이다 확장 된 라틴 문자로 처리됩니다 tr
. 여기서 실제 문제는 tr
모든 문자가 유니 코드이므로 유니 코드를 처리하지 않는 것이 tr
아니라 실제로 한 번에 1 바이트 만 처리하는 것입니다.
난 그냥 awk를 사용합니다
awk -F\" '{print NF-1}' <fileName>
여기서는 필드 구분 기호 (-F 플래그 사용)를 문자로 설정 "
한 다음 필드 수 NF
-1을 인쇄하기 만하면됩니다. 대상 문자의 발생 횟수는 구분 된 필드 수보다 1이 적습니다.
쉘에 의해 해석되는 재미있는 문자의 경우, 이스케이프를 피해야합니다. 그렇지 않으면 명령 행이 해당 문자를 해석하여 해석합니다. 모두 그래서 "
와 )
당신 (와 필드 분리를 탈출해야합니다 \
).
'
). 또한 빈 줄이있는 이상한 동작이 있습니다.
"
되므로 코드가 작동하도록해야한다고 생각합니다. 날씨를 사용하는 캐릭터에 따라 캐릭터가 탈출해야하지만 bash / tcsh는 모두 탈출해야합니다. "
-F'"'
.
awk -F"$1" '{print NF==0?NF:NF-1}' filename
tr
ard 사용 wc
:
function countchar()
{
while IFS= read -r i; do printf "%s" "$i" | tr -dc "$1" | wc -m; done
}
용법:
$ countchar '"' <file.txt #returns one count per line of file.txt
1
3
0
$ countchar ')' #will count parenthesis from stdin
$ countchar '0123456789' #will count numbers from stdin
$IFS
. 그렇지 않으면 read
시작 및 끝에서 공백 문자가 잘 립니다.
tr
구현은 멀티 바이트 문자를 지원하지만 문자가 아닌 wc -c
바이트 수를 계산합니다 ( wc -m
문자 필요 ).
외부 프로그램에 의존에없는 또 다른 구현 bash
, zsh
, yash
및 일부 구현 / 버전 ksh
:
while IFS= read -r line; do
line="${line//[!\"]/}"
echo "${#line}"
done <input-file
line="${line//[!(]}"
계산에 사용 합니다 (
.
eof=false; IFS=; until $eof; do read -r || eof=true; echo "$REPLY"; done
/
bash에는 필요없는 후행 을 추가했습니다 . ksh 요구 사항입니까?
/
이전 버전의 ksh 에는 후행 이 필요하고 이전 버전의 bash에는 IIRC도 필요합니다.
awk
일치하는 수가 너무 많으면 (나의 상황이 발생하면) 사용하여 대답이 실패합니다. loki-astari 의 답변 에 대해 다음 오류가보고됩니다.
awk -F" '{print NF-1}' foo.txt
awk: program limit exceeded: maximum number of fields size=32767
FILENAME="foo.txt" FNR=1 NR=1
로부터 답변을 enzotib (로부터 해당 manatwork ) 세그먼트 오류가 발생
awk '{ gsub("[^\"]", ""); print length }' foo.txt
Segmentation fault
maxschlepzig 의 sed
솔루션 은 올바르게 작동하지만 느립니다 (아래의 타이밍).
여기에 아직 제안되지 않은 일부 솔루션이 있습니다. 먼저 다음을 사용하십시오 grep
.
grep -o \" foo.txt | wc -w
그리고 사용 perl
:
perl -ne '$x+=s/\"//g; END {print "$x\n"}' foo.txt
다음은 몇 가지 솔루션에 대한 타이밍입니다 (가장 느리게 정렬 됨). 나는 여기에 하나의 라이너로 물건을 제한했습니다. 'foo.txt'는 84922 개의 일치 항목을 포함하는 한 줄과 하나의 긴 문자열이있는 파일입니다.
## sed solution by [maxschlepzig]
$ time sed 's/[^"]//g' foo.txt | awk '{ print length }'
84922
real 0m1.207s
user 0m1.192s
sys 0m0.008s
## using grep
$ time grep -o \" foo.txt | wc -w
84922
real 0m0.109s
user 0m0.100s
sys 0m0.012s
## using perl
$ time perl -ne '$x+=s/\"//g; END {print "$x\n"}' foo.txt
84922
real 0m0.034s
user 0m0.028s
sys 0m0.004s
## the winner: updated tr solution by [maxschlepzig]
$ time tr -d -c '\"\n' < foo.txt | awk '{ print length }'
84922
real 0m0.016s
user 0m0.012s
sys 0m0.004s
awk와 gsub를 사용한 또 다른 가능한 구현 :
awk '{ gsub("[^\"]", ""); print length }' input-file
이 함수 gsub
는 sed 's와 같습니다 's///g'
.
gsub("[^(]", "")
계산에 사용 합니다 (
.
awk '{print gsub(/"/,"")}' input-file
"문자열 t에서 정규 표현식 r과 일치하는 각 하위 문자열에 대해 문자열 s를 대체하고 대체 수를 리턴하십시오." (man awk)
지루한 C 프로그램 원인을 작성하기로 결정했습니다.
아마도 입력 유효성 검사를 추가해야하지만 그 외에는 모두 설정되어 있습니다.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char c = argv[1][0];
char * line = NULL;
size_t len = 0;
while (getline(&line, &len, stdin) != -1)
{
int count = 0;
char * s = line;
while (*s) if(*s++ == c) count++;
printf("%d\n",count);
}
if(line) free(line);
}
free(line)
프로그램을 종료하면 모든 할당 된 메모리가 암시 적으로 해제되므로 return 0;
...;)에 대한 위치가 있기 때문에 제외 할 수 있습니다 . 예제에서도 리턴 코드를 정의되지 않은 상태로 두는 것은 좋지 않습니다. Btw getline
는 누군가가 궁금해하는 경우를 대비하여 GNU 확장입니다.
f
다른 코드에서 여러 번 호출되는 독립 실행 형 함수 인 코드를 리팩토링하는 경우이 함수의 끝에서 free
마지막 호출 후 호출 getline
해야합니다 f
.
다음은 STD C와 적은 메모리 만 필요한 다른 C 솔루션입니다.
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc < 2 || !*argv[1]) {
puts("Argument missing.");
return 1;
}
char c = *argv[1], x = 0;
size_t count = 0;
while ((x = getc(stdin)) != EOF)
if (x == '\n') {
printf("%zd\n", count);
count = 0;
} else if (x == c)
++count;
return 0;
}
\n
이없는 줄은 실제 줄이 아니기 때문에 의도적으로 사용 됩니다. 이것은 내 다른 sed / awk (tr / awk) 답변과 동일한 동작입니다.
더 단순하고 강력하게 만들기 위해 grep
함께 사용할 수 있습니다 regex
.
특정 문자를 계산합니다.
$ grep -o '"' file.txt|wc -l
공백 문자를 포함한 특수 문자를 계산합니다.
$ grep -Po '[\W_]' file.txt|wc -l
여기에서 우리는 어떤 캐릭터를 선택하는 [\S\s]
과 함께 -o
옵션 우리는 할 grep
별도의 라인에 각각 일치 (입니다, 각 문자)를 인쇄 할 수 있습니다. 그런 다음 wc -l
각 줄을 세는 데 사용하십시오 .
"
각 줄에 몇 개가 있는지 ; 그리고 다른 문자들. 그의 질문과 대답을 참조하십시오.
아마도 더 직설적 인 순수한 대답은 split을 사용하는 것입니다. Split는 문자열을 가져 와서 배열로 바꾸고, 반환 값은 생성 된 배열 항목 수 + 1입니다.
다음 코드는 각 줄에 "가 나타나는 횟수를 인쇄합니다.
awk ' {print (split($0,a,"\"")-1) }' file_to_parse
분할에 대한 자세한 정보 http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_92.html
순수한 bash 솔루션 (그러나 bash에만 해당) : $x
문자열을 포함하는 변수가 다음과 같은 경우 :
x2="${x//[^\"]/}"
echo ${#x2}
${x//
것은 제외한 모든 문자를 제거합니다 "
, ${#x2}
이 나머지의 길이를 계산합니다.
( expr
문제가있는 원래 제안 , 의견 참조 :)
expr length "${x//[^\"]/}"
expr
문자가 아닌 바이트 수를 계산합니다. 다른 사람과 함께 expr
:expr "x${x...}" : "x.*" - 1
제시된 솔루션의 시간 비교 (답이 아님)
답변의 효율성은 중요하지 않습니다. 그럼에도 불구하고 @josephwb 접근 방식에 따라 제시된 모든 답변의 시간을 맞추려고했습니다.
나는 Victor Hugo "Les Miserables"(great book!)의 포르투갈어 번역을 입력으로 사용하고 "a"의 발생을 계산합니다. 내 에디션에는 5 권의 볼륨이 있으며 많은 페이지가 있습니다 ...
$ wc miseraveis.txt
29331 304166 1852674 miseraveis.txt
C 답변은 gcc로 최적화되었습니다 (최적화 없음).
각 답변은 3 번 실행되었으며 최선을 선택했습니다.
이 숫자를 너무 믿지 마십시오 (내 기계는 다른 작업 등을 수행하고 있습니다). 예상치 못한 결과를 얻었으므로 더 많은 정보를 얻을 수 있으리라 확신합니다.
grep -oP a
트리 시간이 다음보다 빠릅니다 grep -o a
(10; 11 대 12).(임의의 순서로 결과)
=========================1 maxschlepzig
$ time sed 's/[^a]//g' mis.txt | awk '{print length}' > a2
real 0m0.704s ; user 0m0.716s
=========================2 maxschlepzig
$ time tr -d -c 'a\n' < mis.txt | awk '{ print length; }' > a12
real 0m0.022s ; user 0m0.028s
=========================3 jjoao
$ time perl -nE 'say y!a!!' mis.txt > a1
real 0m0.032s ; user 0m0.028s
=========================4 Stéphane Gimenez
$ function countchar(){while read -r i; do echo "$i"|tr -dc "$1"|wc -c; done }
$ time countchar "a" < mis.txt > a3
real 0m27.990s ; user 0m3.132s
=========================5 Loki Astari
$ time awk -Fa '{print NF-1}' mis.txt > a4
real 0m0.064s ; user 0m0.060s
Error : several -1
=========================6 enzotib
$ time awk '{ gsub("[^a]", ""); print length }' mis.txt > a5
real 0m0.781s ; user 0m0.780s
=========================7 user606723
#include <stdio.h> #include <string.h> // int main(int argc, char *argv[]) ... if(line) free(line); }
$ time a.out a < mis.txt > a6
real 0m0.024s ; user 0m0.020s
=========================8 maxschlepzig
#include <stdio.h> // int main(int argc, char **argv){if (argc < 2 || !*argv[1]) { ... return 0; }
$ time a.out a < mis.txt > a7
real 0m0.028s ; user 0m0.024s
=========================9 Stéphane Chazelas
$ time awk '{print gsub(/a/, "")}'< mis.txt > a8
real 0m0.053s ; user 0m0.048s
=========================10 josephwb count total
$ time grep -o a < mis.txt | wc -w > a9
real 0m0.131s ; user 0m0.148s
=========================11 Kannan Mohan count total
$ time grep -o 'a' mis.txt | wc -l > a15
real 0m0.128s ; user 0m0.124s
=========================12 Kannan Mohan count total
$ time grep -oP 'a' mis.txt | wc -l > a16
real 0m0.047s ; user 0m0.044s
=========================13 josephwb Count total
$ time perl -ne '$x+=s/a//g; END {print "$x\n"}'< mis.txt > a10
real 0m0.051s ; user 0m0.048s
=========================14 heemayl
#!/usr/bin/env python2 // with open('mis.txt') as f: for line in f: print line.count('"')
$ time pyt > a11
real 0m0.052s ; user 0m0.052s
=========================15 enzotib
$ time while IFS= read -r line; do line="${line//[!a]/}"; echo "${#line}"; done < mis.txt > a13
real 0m9.254s ; user 0m8.724s
=========================16 bleurp
$ time awk ' {print (split($0,a,"a")-1) }' mis.txt > a14
real 0m0.148s ; user 0m0.144s
Error several -1
grep -n -o \" file | sort -n | uniq -c | cut -d : -f 1
grep은 모든 무거운 리프팅을 수행합니다. 각 줄 번호에서 찾은 각 문자를보고합니다. 나머지는 한 줄당 카운트를 합산하고 출력을 형식화하는 것입니다.
를 제거하고 -n
전체 파일 수를 가져옵니다.
0.015 초 안에 1.5Meg 텍스트 파일을 계산하는 것이 빠른 것 같습니다.
그리고 문자 (바이트가 아닌)와 함께 작동합니다.