Perl을 사용하여 파일의 과학적 숫자 수 계산 3.32242429E-001 3.37272733E-001 3.42303038E-001 3.47333342E-001 3.52363646E-001 3.57393950E-001

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

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

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

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



답변

코어 모듈 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.


답변

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

참고 문헌


답변

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 )


답변

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

tail -n +5 filename | wc - w

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


답변

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

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


답변

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

예를 들어,

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]+)?

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


답변