Perl을 사용하여 파일의 과학적 숫자 수 계산


10

파일에서 과학 수를 세는 방법은 무엇입니까? 파일에는 몇 줄의 헤더가 있으며 건너 뛸 필요가 있습니다.

파일 내용의 일부는 다음과 같습니다.

FileHeaderLine1
FileHeaderLine2
FileHeaderLine3
FileHeaderLine4
2.91999996E-001 2.97030300E-001 3.02060604E-001 3.07090908E-001 3.12121212E-001 3.17151517E-001
3.22181821E-001 3.27212125E-001 3.32242429E-001 3.37272733E-001 3.42303038E-001 3.47333342E-001
3.52363646E-001 3.57393950E-001 3.62424254E-001 3.67454559E-001 3.72484863E-001 3.77515137E-001
3.82545441E-001 3.87575746E-001 3.92606050E-001 3.97636354E-001 4.02666658E-001 4.07696962E-001
4.12727267E-001 4.17757571E-001 4.22787875E-001 4.27818179E-001 4.32848483E-001 4.37878788E-001
4.42909092E-001 4.47939396E-001 4.52969700E-001

그렇다면 위 예제의 처음 네 줄을 건너 뛰고 파일의 과학적 숫자 수를 어떻게 계산할 수 있습니까?

답변:


14

코어 모듈 Scalar::Util을 사용하면 다음을 수행 할 수 있습니다.

$ perl -MScalar::Util=looks_like_number -anle '
    $count += grep { looks_like_number($_) } @F;
    END { print $count }
' file
33

자세한 내용 looks_like_number은에서 볼 수 있습니다 perldoc perlapi.


+1 쿨, 나는 몰랐다looks_like_number
스틸 드라이버

7

GNU grep 사용

grepPCRE 기능을 사용하여이를 수행 할 수 있습니다. 덧붙여서 Perl에서도 같은 패턴을 사용할 수 있습니다 :

$ grep -oP '\d+E[-+]?\d+' file.txt  | wc -l
33

wc -w단어를 계산 하는 데 사용할 수도 있습니다. 위의 줄을 세고 있지만 줄 grep에서 단일 일치 항목을 반환하므로 해당 시나리오에서는 실제로 중요하지 않습니다.

펄 사용하기

Perl의 경우이 하나의 라이너를 사용할 수 있습니다.

$ perl -lane '$c += grep /\d+E[-+]?\d+/, @F; END { print $c; }' file.txt 
33

참고 문헌


@StephaneChazelas-편집 해 주셔서 감사합니다. 유감스럽게도 GNU 시스템에만 있기 때문에 항상이 점을 잊어 버리는 경향이 있습니다. 나는 그런 실수를하지 않으려 고 노력할 것이다.
slm

4

egrep 작동합니다 :

egrep "[0-9].[0-9]E-[0-9]" YourFile | wc -w

최신 정보:

행에 숫자와 다른 문자열이 모두 포함되어 있으면 awk문제를 해결하는 데 사용할 수 있습니다 .

awk -F' ' '{for(i=1;i<=NF;i++)if(!(i%1))$i=$i "\n"}1' YourFile | egrep "[0-9].[0-9]E-[0-9]" | wc -w ( or wc -l )

행에 숫자와 다른 문자열이 모두 포함 된 경우 잘못된 결과가 나타납니다. grep의 -o 옵션을 사용하여 일치 항목 만 출력하는 위의 대답이 더 정확합니다.
Johnny

나는 -oP전에 slm 답변에 언급 된 옵션 에 대해 awk몰랐지만 @Johnny를 사용하여 문제를 해결했습니다.
Nidal

3

네 번째 줄 다음에 과학적 숫자 만 있다고 가정하면 다음과 같이 할 수 있습니다.

tail -n +5 filename | wc - w

제공 한 입력의 경우 위 명령을 실행 한 후 출력은 33 입니다.


3

펄의 헤더 행 다음 에 공백으로 구분 된 필드 수를 계산 해야하는 경우 간단히 할 수 있다고 생각합니다.

perl -lane '$sum += $#F+1 if $. > 4; END{print $sum}' file

과학적으로 형식화 된 숫자 만 계산해야하는 경우 적합한 정규식 에 따라 숫자를 검색하고 바꾸고 교체 횟수를 계산하는 방법이 있습니다 (perl 치환 표현식은 변수에 바인딩 할 때 교체 횟수를 반환 함) )

perl -lane '$sum += s/[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?//g if $. > 4; END{print $sum}' file

2

그것은 실제로 과학적 숫자 로 고려하고자하는 것, 입력에 포함될 것으로 예상되는 것 및 입력에서 해당 숫자를 찾는 위치 로 내려갑니다 .

예를 들어,

That's inferior to the LK2E2000 model.

0 또는 2 (inf 및 2E2000) 또는 3 (inf, 2E200, 0) 숫자를 찾을 수 있습니다 (또는 극단적으로 취해 유효한 숫자를 형성하는 모든 문자 시퀀스를 찾습니다 : 17 (inf, 2, 2E2, 2E20, 2E200, 2E200, 2E2000, 2, 20, 200, 2000, 0, 00, 000, 0, 00, 0)).

입력 내용에 X.XXXXXXXXE-XXX에 숫자 만 있고 자신의 단어로되어 있다는 것을 알고 있다면 다음과 같이 전체 단어로만 찾는 것이 더 안전 할 수 있습니다.

tr -s '[[:blank:]]' '[\n*]' | LC_ALL=C grep -xEc '[0-9]\.[0-9]{8}E-[0-9]{3}'

아이디어는 한 줄에 하나의 단어를 가져 와서 전체 -x패턴 ( )을 원하는 패턴 과 일치시키는 것 입니다. 과학적 표기법 번호 (-1.2e + 1234 ... e또는 a가있는 한 E) 를 허용하려면 패턴을 다음과 같이 변경할 수 있습니다.

[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9])[eE][-+]?[0-9]+

또는 e...모든 종류의 십진 부동 소수점 숫자를 허용하도록 부품을 선택적으로 만드십시오 .

[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9])([eE][-+]?[0-9]+)?

모든 것은 특정 입력에 대해 동일한 대답을 제공하지만 차이가 나는 곳은 샘플에 표시된 엄격한 패턴에서 벗어난 입력이있는 곳입니다.

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