파일 끝에 빈 줄이있는 파일이 있습니다. grep
스크립트에서 파일 이름이 변수로 전달되는 파일 끝의 빈 줄 수를 계산하는 데 사용할 수 있습니까 ?
grep
@MichaelJohn 에게 내 책에서 순결 을 얻었습니다.
파일 끝에 빈 줄이있는 파일이 있습니다. grep
스크립트에서 파일 이름이 변수로 전달되는 파일 끝의 빈 줄 수를 계산하는 데 사용할 수 있습니까 ?
grep
@MichaelJohn 에게 내 책에서 순결 을 얻었습니다.
답변:
빈 줄이 끝에 만 있는 경우
grep -c '^$' myFile
또는:
grep -cx '' myFile
grep -cv . myFile
코드 골퍼를위한 다른 방법입니다. 그러나 grep
파일의 아무 곳에 나 빈 줄이 있으면 해결책을 찾았습니다 .
grep -cv .
는 유효한 문자를 형성하지 않는 바이트 만 포함하는 행도 계산합니다.
재미를 위해서, 짜증나는 것 sed
:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
설명:
/./
임의의 문자로 행을 처리하므로 /./!
비어 있지 않은 행을 처리합니다. 이를 위해 H
명령은 보류 공간에 추가합니다. 따라서 각 빈 줄에 대해 보류 공간에 한 줄을 추가 한 경우 빈 줄 수보다 항상 한 줄이 더 있습니다. 나중에 처리하겠습니다.//h
빈 패턴은 문자 인 마지막 정규식과 일치하므로 비어 있지 않은 행은 주소가 지정되고 수집 된 행을 1로 "재설정"하는 명령에 의해 보류 공간으로 이동 됩니다 h
. 다음 빈 행이 추가되면, 예상대로 두 개가 다시있을 것입니다.$!d
마지막 행을 제외한 모든 행에 대해 출력없이 스크립트를 중지하므로 추가 명령은 마지막 행 이후에만 실행됩니다. 보류 공간에서 수집 한 빈 줄은 모두 파일 끝에 있습니다. 좋은.//d
: d
비어 있지 않은 행에 대해서만 명령이 다시 실행됩니다. 따라서 마지막 줄이 비어 있지 sed
않으면 출력없이 종료됩니다. 제로 라인. 좋은.x
교환은 공간과 패턴 공간을 보유하므로 수집 된 라인은 이제 처리 될 패턴 공간에 있습니다.s/\n//
.wc -l
.더 많은 GNU tac
/ tail -r
옵션 :
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
또는:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
다음의 출력에 유의하십시오.
printf 'x\n '
즉, 마지막 전체 줄 다음에 여분의 공백이있는 경우 (일부는 여분의 빈 줄로 간주 될 수 있지만 POSIX 텍스트 정의에 의해 유효한 텍스트가 아님) 0을 제공합니다.
POSIXly :
awk 'NF{n=NR};END{print NR-n}' < file
그러나 그것은 파일을 완전히 읽는 것을 의미합니다 ( tail -r
/ tac
는 찾기 가능한 파일의 끝에서 파일을 뒤로 읽습니다). 그것은 1
의 출력을 제공합니다 printf 'x\n '
.
실제로 grep
솔루션을 요구할 때 GNU에만 의존하는 이것을 추가합니다 grep
(좋아요, 쉘 구문과 echo
...을 사용합니다).
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
내가 여기서 뭘하고있는 거지? $(grep -c ".*" "$1")
파일의 모든 줄을 세고, 마지막 빈 줄없이 파일을 뺍니다.
어떻게 구할 수 있습니까? $(grep -B42 . "$1"
비어 있지 않은 줄과 42 줄을 모두 앞에 그리십시오. 비어 있지 않은 줄 앞에 42 줄을 넘지 않는 한 마지막 비어 있지 않은 줄까지 모든 것을 인쇄합니다. 이 한계를 피하기 위해 옵션 $(grep -cv . "$1")
의 매개 변수로 사용합니다 -B
. 이는 빈 줄의 총 수이므로 항상 충분히 큽니다. 이 방법으로 후행 빈 줄을 제거하고 줄 |grep -c ".*"
을 계산하는 데 사용할 수 있습니다 .
훌륭하지 않습니까? (-;
tac | grep
공백이 아닌 첫 번째 공백이 아닌 -m -A 42
다음에 빼는 것입니다. 어느 것이 더 효율적인지 잘 모르겠지만 wc -l | cut -d' ' -f1
빈 줄을 잡는 대신에?
tac
, wc
그리고 cut
있지만, 나는 여기에 자신을 제한하기 위해 노력했다 grep
. 당신은 그것을 불변이라고 부를 수 있습니다. (-;
또 다른 awk
해결책. 이 변형 k
은 빈 줄이 없을 때마다 카운터를 다시 설정합니다 . 그런 다음 모든 줄이 카운터를 증가시킵니다. (따라서 첫 번째 공백이 아닌 길이 줄 뒤에 k==0
.) 끝에서 계산 한 줄 수를 출력합니다.
데이터 파일 준비
cat <<'X' >input.txt
aaa
bbb
ccc
X
샘플에서 마지막 빈 줄을 세십시오.
awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3
이 정의에서 빈 줄은 공백이나 다른 빈 문자를 포함 할 수 있습니다. 여전히 비어 있습니다. 빈 줄 대신 빈 줄을 세려면으로 변경 NF
하십시오 $0 != ""
.
$0 > ""
? 그것은 많은 구현에서 사용 strcoll()
하는 것보다 덜 효율적인 것을 $0 != ""
사용합니다 memcmp()
(POSIX는 그것을 사용하도록 요구했습니다 strcoll()
).
$0 > ""
다를 수도 있다고 생각하지 않았습니다 $0 != ""
. awk
어쨌든 "느린"연산자 로 취급하는 경향이 있습니다 (내가 입력으로 큰 데이터 세트를 가지고 있고 처리가 시간이 중요하다는 것을 알고 있다면 처리해야 할 양을 줄이기 위해 내가 할 수있는 일을 보게 될 것입니다 awk
-I grep | awk
그런 상황에서 구조를 사용 했습니다). 그러나 내가 생각하는 것을 간략하게 살펴보면 POSIX 정의가 나 strcoll()
또는에 대한 참조를 볼 수 없습니다 memcmp()
. 내가 무엇을 놓치고 있습니까?
strcoll()
== 문자열은 로케일 별 조합 순서를 사용하여 비교해야합니다 . 이전 판 과 비교하십시오 . 나는 그것을 키우는 사람이었습니다. 참조 austingroupbugs.net/view.php?id=963
a <= b && a >= b
와 반드시 동일하지 않은 구현 a == b
. 아야!
awk
이나 bash
(그에 [[ a < b ]]
대한 예를 들어 GNU 시스템은 en_US.UTF-8 로켈에서 사업자) ①
대 ②
예를 들어 (대한 bash
의 없음, <
, >
, =
true를 반환). 논란의 여지는 더 떠들썩한 파티 / AWK보다 그 로케일의 정의의 버그입니다
파일 끝에서 연속적인 빈 줄 수를 계산합니다.
고체 awk
+ tac
용액 :
샘플 input.txt
:
$ cat input.txt
aaa
bbb
ccc
$ # command line
행동 :
awk '!NF{ if (NR==++c) { cnt++ } else exit }END{ print int(cnt) }' <(tac input.txt)
!NF
-현재 행이 비어 있는지 확인합니다 (필드가 없음).NR==++c
-빈 줄의 연속 순서를 보장합니다. ( NR
-레코드 번호 ++c
-균등하게 증가 된 보조 카운터)cnt++
- 빈 줄의 카운터출력 :
3
IIUC, 다음 스크립트 count-blank-at-the-end.sh
가 작업을 수행합니다.
#!/usr/bin/env sh
count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))
printf "%s\n" "$num_of_blank_lines"
사용법 예 :
$ ./count-blank-at-the-end.sh FILE
4
나는 그것을에서 테스트 GNU bash
, Android mksh
및의 ksh
.
대체 Python
솔루션 :
샘플 input.txt :
$ cat input.txt
aaa
bbb
ccc
$ # command line
행동 :
python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt
출력 :
3
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile