Bir dosyadaki bilimsel sayı sayısını saymak için Perl kullanma


10

Bir dosyadaki bilimsel sayıların sayısını nasıl sayabilirim? Dosya ayrıca atlanması gereken birkaç başlık satırı içerir.

Dosya içeriğinin bir kısmı aşağıdadır.

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

Peki, yukarıdaki örneğin ilk dört satırını nasıl atlayabilir ve dosyadaki bilimsel sayıların sayısını nasıl sayabilirim?

Yanıtlar:


14

Çekirdek modül ile Scalar::Utilşunları yapabilirsiniz:

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

Hakkında daha fazla bilgi looks_like_numbergörebilirsiniz perldoc perlapi.


+1 güzel, bilmiyordumlooks_like_number
steeldriver

7

GNU grep kullanma

Sen kullanabilirsiniz grepPCRE imkanlarını kullanarak, bunu yapmak için. Bu arada Perl'de de aynı desen kullanılabilir:

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

wc -wKelimeleri saymak için de kullanabilirsiniz , yukarıdaki satırları sayıyorum, ancak grepbir satırdaki tek bir eşleşmeyi döndürür, böylece bu senaryoda gerçekten önemli değildir.

Perl Kullanımı

Perl için bu tek astarı kullanabilirsiniz:

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

Referanslar


@StephaneChazelas - düzenleme için teşekkürler. Üzgünüm, sadece GNU sistemlerinde çalışıyorum, bu yüzden bu noktayı her zaman unutmaya eğilimliyim. Bu hatayı yapmamaya çalışacağım.
slm

4

egrep çalışacak:

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

GÜNCELLEME:

bir satır hem sayı hem de başka bir dize içeriyorsa awk, sorunu çözmek için kullanabiliriz :

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 )

Bir satır hem sayı hem de başka bir dize içeriyorsa bu yanlış sonuçlar verir. Yukarıdaki eşleşmeleri grep'in -o seçeneğini kullanarak yalnızca eşleşmeleri çıktılamak daha doğru olur.
Johnny

Daha -oPönce slm cevabında belirtilen seçenek hakkında bilmiyordum , ama awk@Johnny
Nidal

3

4. satırdan sonra yalnızca bilimsel sayılarınız olduğunu varsayarsak, aşağıdaki gibi bir şey yapabilirsiniz.

tail -n +5 filename | wc - w

Girdiğiniz giriş için yukarıdaki komut çalıştırıldıktan sonra çıkış 33'tür .


3

Perl'deki başlık satırlarını takip eden boşlukla ayrılmış alanların sayısını saymanız gerekiyorsa, sadece

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

Gerçekten yalnızca bilimsel olarak biçimlendirilmiş sayıları saymanız gerekiyorsa, bir yaklaşım uygun bir regex'e göre sayıları aramak ve değiştirmek ve daha sonra değiştirme sayısını saymak olabilir (perl ikame ifadesi, bir değişkene bağladığınızda değiştirme sayısını döndürür) )

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

2

Her şey aslında bir bilimsel sayıyı dikkate almak istediğiniz şeye, girdinizin içermesini bekleyebileceğiniz ve bu sayıları girdide bulmayı kabul edebileceğiniz yere gider.

Örneğin:

That's inferior to the LK2E2000 model.

Geçerli bir sayı oluşturan tüm karakter dizilerini arayarak 0 veya 2 (inf ve 2E2000) veya 3 (inf, 2E200, 0) sayılarını bulabilirim (ya da en uç noktalara götürdüm): 17 (inf, 2, 2E2, 2E20, 2E200, 2E200, 2E2000, 2, 20, 200, 2000, 0, 00, 000, 0, 00, 0)).

Girişinizin yalnızca X.

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

Buradaki fikir, her satıra bir kelime almak ve tüm satırı ( -x) istediğiniz kalıpla eşleştirmek . Herhangi scientify gösterim sayısını izin vermek için (-1.2e + 1234 ... sürece orada olarak eya E), modelle değiştirmek olabilir:

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

Veya e...her türlü ondalık kayan noktalı sayıya izin vermek için parçayı isteğe bağlı yapın:

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

Bu, sizin spesifik girdiniz için aynı cevabı verir, ancak bunun bir fark yaratacağı yerde, örneğinizde gösterilen katı modelden ayrılan girdinin olduğu yerdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.