คุณจะนับคำที่เกิดขึ้นในไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันได้อย่างไร


10

คุณจะนับคำที่เกิดขึ้นในไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันได้อย่างไร - และไดเรกทอรีย่อย (?)

ฉันได้อ่านสิ่งนี้แล้วคุณจะใช้grep; คำสั่งที่แน่นอนคืออะไร?

นอกจากนี้ยังสามารถใช้คำสั่งข้างต้นได้หรือไม่

คำตอบ:


12

การใช้grep+ wc(สิ่งนี้จะรองรับการเกิดขึ้นหลายคำในบรรทัดเดียวกัน):

grep -rFo foo | wc -l
  • -rในgrep: ค้นหาแบบวนซ้ำในลำดับชั้นไดเรกทอรีปัจจุบัน
  • -Fในgrep: จับคู่กับสตริงคงที่แทนกับรูปแบบ;
  • -oในgrep: พิมพ์เฉพาะการจับคู่;
  • -lในwc: พิมพ์จำนวนบรรทัด;
% tree                 
.
├── dir
│   └── file2
└── file1

1 directory, 2 files
% cat file1 
line1 foo foo
line2 foo
line3 foo
% cat dir/file2 
line1 foo foo
line2 foo
line3 foo
% grep -rFo foo | wc -l
8

ฉันคิดว่าอร่อยที่สุด
Jacob Vlijm

1
@JacobVlijm ขอบคุณ! ฉันชอบคุณเหมือนกัน (และอัปเดตมันแล้ว)
kos

ฉันคิดว่าPCREsไม่ควรใช้เนื่องจากเป็นรุ่นทดลอง
Edward Torvalds

2
PCRE ไม่ใช่ "รุ่นทดลอง" แต่พวกเขาก็ไม่ได้คอมไพล์ใน grep เสมอไป (ซึ่งเป็นเหตุผลที่ฉันใช้ pcregrep เมื่อฉันต้องการ) ในกรณีนี้พวกเขาไม่จำเป็นเนื่องจากคำถามถามเกี่ยวกับ "คำว่า" ซึ่งน่าจะเป็นสตริงคงที่ไม่ใช่รูปแบบใด ๆ ดังนั้น-Fอาจจะเร็วกว่า
dannysauer

2
@dannysauer ฉันใช้ PCREs เพราะด้วยเหตุผลบางอย่าง (ผิด) ฉันคิดว่าพวกเขาจำเป็นต้องจับคู่เหตุการณ์ที่เกิดขึ้นหลายครั้งในบรรทัดเดียวกัน แต่จริงๆแล้วพวกเขาไม่ใช่ ฉันก็ไม่ได้ลองใช้แทน-F -Pขอบคุณสำหรับคำแนะนำที่ดีการอัปเดตโดยใช้-Fซึ่งเหมาะกับที่นี่จริง ๆ
kos

8

grep -Rc [term] *จะทำเช่นนั้น การ-Rตั้งค่าสถานะหมายความว่าคุณต้องการค้นหาไดเรกทอรีปัจจุบันซ้ำและไดเรกทอรีย่อยทั้งหมด *ความหมายตัวเลือกไฟล์: ไฟล์ทั้งหมด -cธงจะทำให้grepการส่งออกเพียง แต่จำนวนของการเกิดขึ้น อย่างไรก็ตามหากคำนั้นเกิดขึ้นหลายครั้งในบรรทัดเดียวคำนั้นจะถูกนับเพียงครั้งเดียว

จากman grep:

  -r, --recursive
          Read all files under each directory, recursively, following symbolic links only if they are on the command line.
          This is equivalent to the -d recurse option.

   -R, --dereference-recursive
          Read all files under each directory, recursively.  Follow all symbolic links, unlike -r.

หากคุณไม่มีลิงก์สัญลักษณ์ในไดเรกทอรีของคุณไม่มีความแตกต่าง


คุณสามารถเพิ่มธง-c grepจากนั้น grep นับตัวเองและคุณไม่จำเป็นต้องใช้wc
Wayne_Yux

คุณอาจต้องการใส่--ก่อน*
Edward Torvalds

2
*จะขยายตัวออกไปไม่ใช่ dotfiles ดังนั้นคุณจึงพลาดเหล่านั้นทั้งหมด มันสมเหตุสมผลมากกว่าที่จะเพียงแค่ใช้ "" เนื่องจากคุณจะดำเนินการกับข้อโต้แย้งแบบวนซ้ำ - และนั่นจะเป็นจุดไฟล์ ปัญหาที่ใหญ่กว่าที่นี่คือสิ่งนี้จะทำให้จำนวนบรรทัดไม่ใช่จำนวนครั้งของคำ หากคำนั้นปรากฏหลายครั้งในหนึ่งบรรทัดคำสั่งนั้นจะถูกนับเพียงครั้งเดียวโดย "grep -c"
dannysauer

2

ในสคริปต์หลามขนาดเล็ก:

#!/usr/bin/env python3
import os
import sys

s = sys.argv[1]
n = 0
for root, dirs, files in os.walk(os.getcwd()):
    for f in files:
        f = root+"/"+f      
        try:
            n = n + open(f).read().count(s)
        except:
            pass
print(n)
  • count_string.pyบันทึกเป็น
  • รันจากไดเร็กทอรีด้วยคำสั่ง:

    python3 /path/to/count_string.py <term>
    

หมายเหตุ

  • หากคำนั้นรวมช่องว่างให้ใช้เครื่องหมายคำพูด
  • มันจะนับการเกิดขึ้นทุกครั้งของคำซ้ำรวมถึงการเกิดขึ้นหลายครั้งในหนึ่งบรรทัด

คำอธิบาย:

# get the current working directory
currdir = os.getcwd()
# get the term as argument
s = sys.argv[1]
# count occurrences, set start to 0 
n = 0
# use os.walk() to read recursively
for root, dirs, files in os.walk(currdir):
    for f in files:
        # join the path(s) above the file and the file itself
        f = root+"/"+f
        # try to read the file (will fail if the file is unreadable for some reason)
        try:
            # add the number of found occurrences of <term> in the file
            n = n + open(f).read().count(s)
        except:
            pass
print(n)

2
The python guy ;) +1
TellMe ทำไม

1
BTW สิ่งที่rootและfหา?
TellMe ทำไม

1
rootเป็นเส้นทางไปยังไฟล์รวมถึง "ด้านบน" ไดเรกทอรีปัจจุบันfเป็นไฟล์ อีกวิธีหนึ่งคือ os.path.join()สามารถใช้ แต่ verbose มากขึ้น
Jacob Vlijm

1
และn = n + open(f).read().count(s)?
TellMe ทำไม

2
ดูเหมือนจะเป็นคำตอบเดียวที่นับรวมคำทั้งหมดที่เกิดขึ้นตามที่ OP ร้องขอ AFAIK คำตอบทั้งหมดที่ใช้ grep จะนับบรรทัดทั้งหมดที่คำนั้นเกิดขึ้นดังนั้นบรรทัดที่มีคำสามครั้งจะนับรวมเป็นหนึ่งครั้งเท่านั้น
โจ

2

เป็นตัวแปรของคำตอบที่ดีของ @ kos หากคุณสนใจในการนับจำนวนการนับคุณสามารถใช้-cสวิตช์ของ grep เพื่อนับเหตุการณ์ที่เกิดขึ้น:

$ grep -rFoc foo
file1:3
dir/file2:3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.