ใช้ 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_numberperldoc perlapi


+1 เท่ฉันไม่รู้looks_like_number
steeldriver

7

การใช้ GNU grep

คุณสามารถใช้grepสิ่งนี้โดยใช้สิ่งอำนวยความสะดวก PCRE อนึ่งรูปแบบเดียวกันนี้สามารถใช้ใน Perl ได้เช่นกัน:

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

นอกจากนี้คุณยังสามารถใช้wc -wในการนับคำฉันกำลังนับบรรทัดด้านบน แต่การgrepคืนค่าการจับคู่เดียวในบรรทัดดังนั้นมันไม่สำคัญในสถานการณ์นั้น

ใช้ Perl

สำหรับ 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

UPDATE:

หากสายเกิดขึ้นมีทั้งตัวเลขและสตริงอื่นเราสามารถใช้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 )

สิ่งนี้จะให้ผลลัพธ์ที่ไม่ถูกต้องหากมีบรรทัดเกิดขึ้นที่มีทั้งตัวเลขและสตริงอื่น คำตอบข้างต้นที่ใช้ตัวเลือก -p grep ของการส่งออกการแข่งขันเท่านั้นที่ถูกต้องมากขึ้น
จอห์นนี่

ฉันไม่รู้เกี่ยวกับ-oPตัวเลือกที่กล่าวถึงในคำตอบ slm ก่อนหน้านี้ แต่ฉันได้แก้ไขปัญหาของฉันโดยใช้awk@Johnny
Nidal

3

สมมติว่าคุณมีเพียงตัวเลขทางวิทยาศาสตร์หลังจากบรรทัดที่ 4 คุณสามารถทำสิ่งที่ต้องการด้านล่าง

tail -n +5 filename | wc - w

สำหรับอินพุตที่คุณระบุเอาต์พุตคือ33หลังจากรันคำสั่งด้านบน


3

หากคุณต้องการนับจำนวนฟิลด์ที่คั่นด้วยช่องว่างตามบรรทัดส่วนหัวใน Perl ฉันคิดว่าคุณสามารถทำได้

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

หากคุณต้องการนับเฉพาะตัวเลขที่จัดรูปแบบทางวิทยาศาสตร์จริงๆแล้ววิธีการหนึ่งอาจจะค้นหาและแทนที่ตัวเลขตามregex ที่เหมาะสมแล้วนับจำนวนการแทนที่ (นิพจน์การแทนที่ 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.XXXXXXXXXE-XXX และการที่พวกเขาใช้คำพูดของพวกเขาเองมันอาจจะปลอดภัยกว่าหากค้นหาด้วยคำทั้งหมดเช่น:

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

ความคิดที่นั่นคือการได้รับหนึ่งคำต่อบรรทัดและเพื่อให้ตรงกับทั้งบรรทัด ( -x) กับรูปแบบที่คุณต้องการ หากต้องการอนุญาตหมายเลขโน้ตทางวิทยาศาสตร์ (-1.2e + 1234 ... ตราบใดที่มีeหรือ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.