Bash: có cách nào để tìm kiếm một chuỗi cụ thể trong một thư mục của các tệp không? [bản sao]


47

Có thể trùng lặp:
Tìm kiếm một mẫu văn bản trong linux

Trong bash, tôi đã tự hỏi nếu có bất kỳ lệnh nào sẽ cho bạn biết nếu một chuỗi cụ thể mà bạn đang tìm kiếm tồn tại trong các tệp nằm trong thư mục hiện tại bạn đang ở.

Giả sử bạn đang tìm kiếm hàm 'toUpperCase ()' trong một tập hợp các tệp C trong thư mục hiện tại của bạn. Có rất nhiều tệp, vì vậy bạn sẽ không muốn tự mở từng tệp bằng cách sử dụng vim và kiểm tra chuỗi 'toUpperCase' vì điều đó sẽ mất rất nhiều thời gian. Nếu không phải là một dòng lệnh bash, có một phương pháp khác để làm điều này một cách hiệu quả?

Câu trả lời:


64

Với grep:

grep -R "toUppercase()" *

Hoặc, nếu bạn đã cài đặt ack-grep , chỉ cần:

ack-grep "toUppercase"

Nếu bạn muốn giới hạn tìm kiếm trong tệp C, với ack-grep:

ack-grep -cc "toUppercase()"

ack-grepcũng có thể được cài đặt trên OSX nhưng tệp thực thi được gọi là chỉ ack.


Nhiều đến nỗi SO đã có một câu hỏi tương tự đáng ngờ ;)
David Perry

10

Công cụ tìm kiếm văn bản tiêu chuẩn là grep .

Để tìm chuỗi toUpperCase(trong tất cả .ccác tệp trong thư mục hiện tại:

grep -F 'toUpperCase(' *.c

Nếu bạn muốn tìm trong thư mục con là tốt:

grep -r --include='*.c' -F 'toUpperCase('

Nếu bạn đang tìm kiếm các cuộc gọi chức năng C, thì ctags có thể phù hợp hơn. Bạn chạy nó một lần trên tất cả các tệp nguồn của mình để tạo một chỉ mục định danh, sau đó sử dụng trình chỉnh sửa của bạn để điều hướng giữa các cuộc gọi. Tất cả các biên tập viên giống như vi có thể sử dụng TAGStệp của ctags . Nếu bạn sử dụng Emacs, hãy chạy chương trình tương tự etags.


ctagslà hữu ích để tìm định nghĩa hàm , không phải là hàm gọi .
JdeBP

6

Bạn đang sử dụng vim. Bạn đã có một công cụ để thực hiện việc này.

Có thể dự đoán, có bảy câu trả lời đã nói để sử dụng grep. Nhưng tôi dường như là người duy nhất cho đến nay đã nhận thấy từ câu hỏi của bạn rằng bạn đang sử dụng vim. Như vậy, mặc dù bạn có thể sử dụng greptừ bên trong vim, bạn cũng có thể sử dụng vimcông cụ tích hợp sẵn. Điều này được gọi thông qua :vimgreplệnh.

Để tìm kiếm "tất cả các tệp nguồn C trong thư mục hiện tại cho các cuộc gọi đến hàm toUpperCase()", hãy gõ một vimlệnh

:vimgrep "\<toUpperCase\_s*(" *.c

Danh sách kết quả khớp được tự động tải lên danh sách quickfix, có thể truy cập bằng một trong hai (xem trợ giúp trực tuyến để biết sự khác biệt tinh tế)

:copen
:cwin

Để tìm định nghĩa hàm , thay vì gọi đến nó, ctagslà công cụ, như được đề cập trong Gillescâu trả lời , kết hợp với các lệnh :tjumphoặc :tselect.

Tại sao nên sử dụng :vimgrep?

Trợ giúp trực tuyến ( :help grep) liệt kê một số lý do mà tôi sẽ không vẹt ở đây. Hơn nữa để những, so sánh tác động của :vimgrepvới các dietbuddha's câu trả lời . dietbuddhaDòng lệnh tạo ra một grepquy trình riêng cho từng tệp nguồn C riêng lẻ. Nó thậm chí không sử dụng xargsđể giảm chi phí đó. Và bạn vẫn phải phân tích đầu ra bằng cách nào đó để gọi trình soạn thảo văn bản của bạn trên các tệp nguồn có liên quan sau khi hoàn tất. :vimgrepkhông bỏ qua nhiều quá trình bổ sung, và sử dụng kết quả là chính sự đơn giản. Chỉ cần chọn một trong các mục trong danh sách quickfix kết quả sẽ tự động định vị con trỏ trên dòng có liên quan của tệp nguồn có liên quan.

Trong thực tế, nó thực hiện chính xác những gì bạn đã viết bạn sẽ làm bằng tay, ngoại trừ tự động. Đó là cách tự động để thực hiện những hành động soạn thảo văn bản. Nó tải tệp lên như thể được tải bằng tay, tìm kiếm biểu thức chính quy (sử dụng cùng một cú pháp biểu thức chính quy mà bạn đang sử dụng ở nơi khác vim), ghi lại các vị trí xảy ra khớp và sau đó dỡ tệp.


2

Vâng, công cụ được gọi grep.

Lệnh grep tìm kiếm một hoặc nhiều tệp đầu vào cho các dòng chứa khớp với mẫu đã chỉ định. Theo mặc định, grep in các dòng phù hợp.

Cách sử dụng cơ bản là:

grep something somewhere

Hay cụ thể hơn:

grep [some options] pattern file

Trong một trường hợp rất đơn giản, bạn đệ quy muốn tìm kiếm trong tất cả các tệp, do đó bạn cung cấp -rtùy chọn. Nếu bạn không quan tâm đến chữ hoa hoặc chữ thường, hãy làm cho nó không phân biệt chữ hoa chữ thường với -itùy chọn này.

grep -ri "touppercase()" .

Nếu bạn chỉ muốn các phần phù hợp, sử dụng -otùy chọn.

Grep có thể sử dụng các biểu thức thông thường , và nó có một hướng dẫn rất lớn .


2

greplà câu trả lời chuẩn - sử dụng cờ -r để tìm kiếm đệ quy hoặc kết hợp với find(thảo luận và ví dụ trong các câu hỏi khác trên trang web này, chẳng hạn như câu hỏi này )

Lựa chọn ưa thích của tôi gần đây là ack. Nó không có khả năng được cài đặt trên máy tính của bạn, nhưng bạn có thể cài đặt bằng apt-get trên Ubuntu hoặc chỉ cần tải xuống. Liên kết, hướng dẫn và lý do tốt hơn grep có sẵn tại http://betterthangrep.com/


1

findgrep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

Tại sao không chỉ grep?

grep -r string .sẽ lặp lại thông qua tất cả các tập tin trong thư mục hiện tại. Nếu bạn có tệp đối tượng hoặc các tệp nhị phân khác, bạn có thể lấy lại kết quả trùng khớp với kết quả nhị phân aka. rác. Nếu bạn cũng có các tập tin fifos hoặc thiết bị trong thư mục con của bạn, bạn có thể có những hậu quả không xác định / không lường trước được.

grep string *.cchỉ tìm kiếm các .ctập tin thư mục hiện tại .

grep string **/*.c không tìm kiếm tất cả các thư mục con. Tuy nhiên, nếu bạn có số lượng .ctệp rất lớn, bạn có nguy cơ vượt quá số lượng mở rộng tối đa cho hệ vỏ. Việc mở rộng cũng phải xảy ra trước tiên có nghĩa là một giao dịch toàn cây trước khi grepbắt đầu.


0

Grep sẽ thực hiện thủ thuật nhưng một chút kịch bản bổ sung sẽ giúp tìm tên của tệp và dòng chính xác được tham chiếu. Nếu đó là những gì bạn muốn tôi thấy sau đây hoạt động tốt. Tôi có nó được lưu dưới dạng shell script và truyền cho nó giá trị tôi muốn làm tùy chọn dòng lệnh đầu tiên.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done

3
grep có một tùy chọn -H đã thực hiện điều này. grep -Hn sao cũng được *
Roy Rico

Học một cái gì đó mới mỗi ngày .. Cảm ơn @Roy Rico
Tim Brigham

0

Tôi thấy thú vị khi không ai trả lời câu hỏi cụ thể của bạn: "làm thế nào để tôi biết liệu một chuỗi cụ thể có tồn tại trong các tệp nằm trong thư mục hiện tại không". Theo tôi biết, không có tùy chọn grep nào chỉ trả về việc có tìm thấy kết quả khớp trong một nhóm tệp hay không. Tùy chọn gần nhất là -l để liệt kê (các) tên tệp. Câu trả lời gần nhất trong số đó là từ tim, với một số điều chỉnh nhỏ:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

Bạn có thể làm cho tập lệnh shell này chung chung hơn bằng cách chấp nhận đối số thứ hai cho phần mở rộng tệp mà không gặp quá nhiều khó khăn.

đôi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.