현재 80열보다 넓은 행 수를 계산하려면 다음을 사용합니다.
$ git grep -h -c -v '^.\{,80\}$' **/*.{c,h,p{l,y}} \
|awk 'BEGIN { i=0 } { i+=$1 } END { printf ("%d\n", i) }'
44984
안타깝게도 저장소에서는 들여쓰기에 탭을 사용하므로 grep
패턴이 정확하지 않습니다. regex
표준 너비 8자 같은 탭을 처리할 수 있는 방법이 있습니까 wc -L
?
이 질문의 목적에 따라 기여자는 일관되게 들여쓰기할 수 있을 만큼 충분히 규율이 있거나 git commit
규율 대신 후크가 있다고 가정할 수 있습니다.
성능 관련 이유로 저는 사내에서 작동하는 솔루션 git-grep(1)
이나 기타 도구를 선호합니다.grep
전처리 파일이 필요하지 않습니다..
답변1
파일을 파이핑하여 전처리합니다 expand
. 유틸리티 expand
는 탭을 적절하게 확장합니다(8자마다 표준 탭 정지를 사용).
find . -type f \( -name '*.[ch]' -o -name '*.p[ly]' \) -exec expand {} + |
awk 'length > 80 { n++ } END { print n }'
답변2
TAB을 8자로 처리하는 대신 GNU는 wc -L
TAB을 터미널에 표시된 대로 처리하고 8열마다 TAB 정지를 사용하므로 "너비"의 범위는 줄 위치에 따라 1~8자입니다. wc -L
또한 다른 문자의 표시 너비(0, 1 또는 2열 너비인지 여부)를 고려하고 합계를 "올바르게" 처리합니다 \f
.\r
$ printf 'abcde\t\n' | wc -L
8
여기에서 다음을 사용하여 이러한 탭을 공백으로 확장할 수 있습니다 expand
(기본적으로 8개 열마다 탭 정지가 있다고 가정하지만 옵션으로 변경할 수 있음).
git grep -h '' ./**/*.{c,h,p{l,y}} | expand | tr '\f\r' '\n\n' | grep -cE '.{81}'
(CR(터미널로 전송될 때 커서를 줄의 시작 부분으로 다시 이동) 및 FF(일부 디스플레이 장치는 페이지 나누기로 이해함)를 LF로 변환하여 동일한 동작을 얻되 wc -L
다른 동작은 무시할 수 있습니다. 어차피 판단하지 마세요. 디스플레이 너비에 어떤 영향을 미칠까요?)
여기에는 탭 문자가 포함되지만 단일 또는 이중 너비 문자는 포함되지 않습니다. expand
현재 GNU 구현은 멀티바이트 문자가 있는 경우(너비가 0이거나 두 배인 문자는 물론) 탭을 올바르게 확장하지 않는다는 점에 유의하십시오 .
$ printf 'ééééé\t\n' | wc -L
8
$ printf 'ééééé\t\n' | expand | wc -L
11
또한 숨겨진 파일이나 숨겨진 디렉터리에 있는 파일은 기본적으로 건너뜁니다. 대괄호 확장은 여러 glob으로 확장되므로 ./**/*.{c,h,p{l,y}}
glob 중 하나가 일치하지 않는 경우에도 오류가 발생합니다( zsh
또는 사용하면 치명적인 오류가 발생함).bash -O failglob
의 경우 다음을 zsh
사용할 수 있습니다../**/*.(c|h|p[ly])(D.)
하나D
숨겨진 파일을 포함하고 .
제한하는 glob정기적인문서.
문자의 실제 너비를 고려하는 솔루션의 경우(모든 텍스트 파일이 로케일의 문자 인코딩으로 인코딩된다고 가정) 다음을 사용할 수 있습니다.
git grep -h '' ./**/*.(c|h|p[ly])(.) | tr '\r\f' '\n\n' |
perl -Mopen=locale -MText::Tabs -MText::CharWidth=mbswidth -lne '
$n++ if mbswidth(expand($_)) > 80;
END{print 0+$n}'
적어도 GNU 시스템에서는 제어 문자의 너비가 및 1 mbswidth()
인 것으로 간주됩니다 . 파일에는 CR, NL, TAB, FF 이외의 제어 문자가 없다고 가정합니다.-1
expand()
답변3
귀하의 의견을 토대로 가정할 수 있는 경우상표문자는 줄의 시작 부분에만 나타나므로 대체 문자를 최소 80자로 계산할 수 있습니다.
- 탭 없음, 최소 81자
- 탭, 최소 73자
- 탭 2개, 65자 이상
- 등.
결과적인 혼란은 다음과 같습니다. 귀하의 awk
명령문은 개별 행 수를 합산하여 총계를 제공합니다.
git grep -hcP '^(.{81,}|\t.{73,}|\t{2}.{65,}|\t{3}.{57,}|\t{4}.{49,}|\t{5}.{41,}|\t{6}.{33,}|\t{7}.{25,}|\t{8}.{17,}|\t{9}.{9,}|\t{10}.)' **/*.{c,h,p{l,y}} |
awk '{ i+=$1 } END { printf ("%d\n", i) }'
답변4
솔루션전임자(에서육). 매우 느리지만.
vi는 UTF-8 데이터를 올바르게 처리할 수 있으므로:
탭을 공백으로 확장하고 제어 문자를 1로 계산하여 \r
\t
\f
\v
올바르게 처리하고 대부분의 작업을 처리합니다.효과적인유니코드 값. 결합 악센트(NKC)와 분해 악센트(NKD)는 물론 키릴 문자, 아랍어, 그리스어, 중국어 등의 문자도 포함됩니다.
$ cat script.sh
#!/bin/bash --
declare -i count=0
for i do
# Set ex script in one variable
a='set expandtab " Expand tabs to spaces
r '"$i"' " Read original file
g/^.\{,80\}$/d " Remove all lines shorter than the value used
wq " Quit '
o=outfile; :>"$o" # Clean output file
ex -s "$o" <<<"$a" # process lines in $i file
count+=$(wc -l <"$o") # count and accumulate number of lines.
done
echo "$count"
호출 스크립트는 다음과 같습니다.
$ script.sh **/*.{c,h,p{l,y}}
44984