Thứ ba, 27/05/2014 | 00:00 GMT+7

Cách cài đặt và sử dụng Ack, một sự thay thế Grep cho các nhà phát triển, trên Ubuntu 14.04

Khi tìm kiếm văn bản trong file hoặc trong cấu trúc folder , các hệ thống giống như Linux và Unix có nhiều công cụ có thể hỗ trợ bạn. Một trong những cách phổ biến nhất trong số này là grep , viết tắt của cụm từ in biểu thức chính quy global .

Sử dụng grep, bạn có thể dễ dàng tìm kiếm bất kỳ mẫu nào có thể được thể hiện bằng các biểu thức chính quy trong bất kỳ tập hợp đầu vào văn bản nào. Tuy nhiên, nó không phải là công cụ nhanh nhất và nó được tạo ra như một công cụ có mục đích chung mà không có bất kỳ loại tối ưu hóa nào.

Để tìm kiếm mã nguồn cụ thể, một công cụ lấy cảm hứng từ grep gọi là ack đã được phát minh. Nó tận dụng các biểu thức chính quy Perl để tìm kiếm mã nguồn một cách hiệu quả cho các mẫu, đồng thời cẩn thận để không đưa vào các kết quả mà bạn không quan tâm.

Trong hướng dẫn này, ta sẽ thảo luận về cách sử dụng ack như một sự thay thế grep siêu hỗ trợ để chọn ra các mẫu từ mã nguồn của bạn. Công cụ ack có sẵn trên bất kỳ nền tảng nào có thể sử dụng Perl, nhưng ta sẽ giới thiệu tiện ích này trên server Ubuntu 14.04.

Cài đặt Ack

Để bắt đầu, bước đầu tiên là cài đặt công cụ ack trên máy tính của bạn.

Trên máy Ubuntu hoặc Debian, việc này đơn giản như cài đặt tiện ích từ repository mặc định . Gói được gọi là ack-grep :

sudo apt-get update sudo apt-get install ack-grep 

Vì file thực thi cũng được cài đặt dưới dạng ack-grep , ta có thể yêu cầu hệ thống của bạn rút ngắn file này thành ack để sử dụng công cụ trên dòng lệnh của ta bằng lệnh lệnh sau:

sudo dpkg-divert --local --divert /usr/bin/ack --rename --add /usr/bin/ack-grep 

Bây giờ, công cụ sẽ phản hồi tên ack thay vì ack-grep .

Nếu bạn đang có kế hoạch sử dụng ack trên các hệ thống khác, phương pháp cài đặt có thể khác nhau. Mô-đun Perl trong CPAN được gọi là App::Ack . Trên các bản phân phối Linux khác, tên gói trong repositories có thể khác nhau.

Ack chú ý đến điều gì

Trước khi ta đi vào cách sử dụng thực tế của ack, ta hãy thảo luận một chút về cách nó khác với grep và những file nào nằm trong lĩnh vực ack.

Công cụ ack được tạo ra đặc biệt để tìm kiếm văn bản trong mã nguồn của chương trình. Do đó, công cụ này đã được tối ưu hóa để tìm kiếm các file nhất định và bỏ qua những file khác.

Ví dụ: nếu bạn đang tìm kiếm cấu trúc folder của dự án của bạn , bạn sẽ hầu như không bao giờ muốn tìm kiếm hệ thống phân cấp repository của hệ thống kiểm soát version . Điều này chứa thông tin về các version file cũ hơn và có thể dẫn đến nhiều bản sao. Ack nhận ra rằng đây không phải là nơi bạn muốn tìm kiếm, vì vậy nó bỏ qua các folder này. Điều này dẫn đến kết quả tập trung hơn, cũng như ít dương tính giả hơn.

Theo cách tương tự, nó sẽ bỏ qua các file backup phổ biến được tạo bởi các editor nhất định. Nó cũng sẽ không cố gắng tìm kiếm các file không mã hóa thường thấy trong các folder nguồn, chẳng hạn như version “thu nhỏ” của file web, file hình ảnh và PDF, v.v. Tất cả những điều này đều dẫn đến kết quả tốt hơn cho hầu hết mọi tìm kiếm. Bạn luôn có thể overrides các cài đặt này trong quá trình thực thi.

Một tính năng khác của ack là nó biết về các file nguồn của các ngôn ngữ khác nhau. Bạn có thể yêu cầu nó tìm tất cả các file Python trong cấu trúc folder . Nó sẽ trả về tất cả các file kết thúc bằng .py , nhưng nó cũng sẽ trả về các file nào bắt đầu bằng các dòng:

<pre>

! <span class = “highlight”> / path / to / </span> python

</pre>

Điều này sẽ trùng với các file được xác định bởi phần mở rộng của chúng và cả các file được hướng dẫn để gọi trình thông dịch Python bằng cách sử dụng các lệnh gọi số ma thuật dòng đầu tiên phổ biến:

<pre>

! <span class = “highlight”> / path / to /preter / to / run </span>

</pre>

Điều này tạo ra một cách mạnh mẽ để phân loại các loại file rất khác nhau là có liên quan. Bạn cũng có thể thêm hoặc sửa đổi các group theo ý thích của bạn .

Chuẩn bị môi trường

Cách tốt nhất để chứng minh sức mạnh của ack là sử dụng nó trên một folder mã nguồn.

May mắn là ta có thể dễ dàng kéo xuống một cây nguồn từ một trang web công cộng như GitHub. Cài đặt git để ta có thể kéo xuống một repository :

sudo apt-get install git 

Bây giờ, ta cần lấy một dự án. Dự án neovim là một ví dụ điển hình vì nó chứa nhiều loại file khác nhau. Hãy sao chép repository đó vào folder chính của ta :

cd ~ git clone https://github.com/neovim/neovim.git 

Bây giờ, hãy chuyển sang folder đó để bắt đầu:

cd neovim 

Kiểm tra các file khác nhau để có ý tưởng về sự đa dạng mà ta có:

ls 

BACKERS.md       CMakeLists.txt   Doxyfile   scripts      uncrustify.cfg clint-files.txt  config           Makefile   src          vim-license.txt clint.py         contrib          neovim.rb  test cmake            CONTRIBUTING.md  README.md  third-party 

Chỉ trong folder cấp cao nhất đó, ta thấy các file đánh dấu, văn bản thuần túy, file Ruby, file Python. Và phần chính của dự án được viết bằng C.

Ta cũng muốn cài đặt một số điều để giúp cuộc sống của ta dễ dàng hơn.

Ta muốn chuyển kết quả trực tiếp thành less nếu kết quả lớn hơn cửa sổ terminal của ta . Điều này sẽ ngăn kết quả cuộn không kiểm soát được khỏi màn hình.

Làm điều đó bằng lệnh :

echo '--pager=less -RFX' >> ~/.ackrc 

Thao tác này sẽ tạo file cấu hình ack của ta và thêm tùy chọn không mặc định đầu tiên của nó. Ta yêu cầu nó chuyển kết quả thành less với một số tùy chọn cho phép nó hiển thị kết quả có màu và xử lý đường chuyền một cách thông minh.

Tìm kiếm đơn giản với Ack

Bắt đầu nào. Để bắt đầu, hãy để tôi chứng minh sự khác biệt giữa những gì grep sẽ tìm kiếm và những gì ack tìm kiếm.

Grep tìm kiếm mọi file trong cấu trúc folder để tìm các file trùng khớp. Ta có thể xem tổng số file trong dự án này bằng lệnh :

find . | wc -l 

566 

Tại thời điểm viết bài này, có tổng cộng 566 file trong dự án neovim. Để biết có bao nhiêu file mà ack quan tâm, ta có thể nhập:

ack -f | wc -l 

497 

Như bạn thấy , ta đã loại bỏ khoảng 12% file được tìm kiếm mà thậm chí không cần làm gì cả.

Giả sử ta muốn tìm hiểu tất cả các trường hợp mà mẫu "hạn chế" được tìm thấy trong dự án này. Ta có thể gõ:

ack restrict 

Doxyfile 1851:# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. 1860:# code bases. Also note that the size of a graph can be further restricted by 1861:# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.  vim-license.txt 3:I)  There are no restrictions on distributing unmodified copies of Vim except 5:    unmodified parts of Vim, likewise unrestricted except that they must . . . 

Như bạn thấy , ack chia các trường hợp "hạn chế" theo file nơi tìm thấy các kết quả phù hợp. Hơn nữa, nó cung cấp số dòng chính xác.

Nhưng như bạn thấy , một số trường hợp (tất cả phần mẫu mà tôi đã sao chép) là các biến thể phù hợp của “hạn chế” như “hạn chế” và “hạn chế”. Điều gì sẽ xảy ra nếu ta chỉ muốn từ "hạn chế"?

Ta có thể sử dụng cờ -w để yêu cầu nó tìm kiếm các trường hợp mẫu của ta được bao quanh bởi các ranh giới từ. Điều này sẽ loại bỏ các thì khác của từ:

ack -w restrict 

vim-license.txt 37:       add.  The changes and their license must not restrict others from  clint.py 107:      Specify a number 0-5 to restrict errors to certain verbosity levels.  src/nvim/fileio.c 6846:   * Allow nesting of autocommands, but restrict the depth, because it's . . . 

Như bạn thấy , kết quả của ta hiện chỉ hiển thị "hạn chế" mà không có các biến thể mà ta đã thấy trước đây. Đầu ra được chú trọng hơn rất nhiều.

Bạn có thể nhận thấy ở trên rằng các kết quả mà ta có được tìm thấy ở các loại file khác nhau. Một là file văn bản thuần túy, có một trường hợp được tìm thấy trong file Python và có nhiều trường hợp trong file nguồn C.

Nếu ta muốn yêu cầu ack chỉ hiển thị cho ta kết quả được tìm thấy trong các file Python, ta có thể thực hiện việc này một cách dễ dàng bằng lệnh :

ack -w --python restrict 

clint.py 107:      Specify a number 0-5 to restrict errors to certain verbosity levels. 

Ta không phải chỉ định các mẫu file mà ta đang tìm kiếm. Ta không phải tạo các biểu thức chính quy đặc biệt để bắt loại file ta muốn mà không cần trùng với những file khác. Ack chỉ đơn giản là biết các file của nhiều ngôn ngữ phổ biến và bạn có thể tham khảo chúng theo tên.

Ta sẽ xem xét cách bạn có thể sửa đổi các file ack trả về cho từng ngôn ngữ và cách xác định các group ngôn ngữ của bạn sau.

Phân tích Trọng tâm Tìm kiếm của ta

Ta đã đi từ một kết quả rất rộng, đến một kết quả duy nhất bằng cách thêm một số cờ rất đơn giản. Hãy xem chính xác ta đã thu hẹp kết quả của bạn đến mức nào.

Ta có thể sử dụng cờ -ch , mà ta có thể coi như một thành ngữ đơn giản nghĩa là “có bao nhiêu trận đấu được trả về?”. Tự nó, cờ -c yêu cầu ack chỉ trả về số lượng dòng phù hợp trong mỗi file , như sau:

ack -c restrict 

Doxyfile:3 Makefile:0 uncrustify.cfg:0 .travis.yml:0 neovim.rb:0 vim-license.txt:5 

Thao tác này sẽ trả về một dòng cho mọi file , ngay cả những file không trùng khớp.

Cờ -h tự nó loại bỏ tiền tố tên file trong kết quả và loại bỏ các file không có kết quả. Cùng nhau, họ sẽ đưa ra một số duy nhất đại diện cho số dòng mà tìm kiếm được so khớp:

ack -ch restrict 

101 

Ta bắt đầu với 101 kết quả. Khi ta yêu cầu nó chú ý đến ranh giới từ, ta đã cắt một phần lớn trong số này:

ack -ch -w restrict 

16 

Và tất nhiên, khi ta chỉ định rằng ta chỉ muốn xem các file Python, ta đã thu hẹp kết quả của bạn thành một đối sánh duy nhất:

ack -ch -w --python restrict 

1 

Ta không chỉ thu hẹp phạm vi tìm kiếm mà bằng cách thêm giới hạn ngôn ngữ, ta đã thực sự tăng tốc tìm kiếm. Ack không chỉ đơn giản lọc kết quả dựa trên ngôn ngữ bạn yêu cầu, nó thực hiện điều này trước khi tìm kiếm để tự cứu mình khỏi phải tìm kiếm các file không liên quan.

Ta có thể thấy điều này bằng cách xác định thời gian tìm kiếm bằng lệnh time :

time ack -ch restrict 

101  real    0m0.407s user    0m0.363s sys     0m0.041s 

Bây giờ, hãy thử tìm kiếm tập hợp con theo ngôn ngữ cụ thể:

time ack -ch -w --python restrict 

1  real    0m0.204s user    0m0.175s sys     0m0.028s 

Thứ hai là nhanh hơn đáng kể.

Sửa đổi kết quả tìm kiếm

Ta đã nói về việc sửa đổi kết quả tìm kiếm một chút khi ta xem xét các cờ -c-h . Có những cờ hữu ích khác có thể giúp ta định hình kết quả mà ta muốn.

Ví dụ, như bạn đã thấy trước đây, cờ -c in ra số dòng nơi tìm thấy một mẫu đối sánh trong mỗi file . Trước đây, ta đã sửa đổi nó bằng -h , nhưng ta cũng có thể sửa đổi nó bằng -l . Điều này sẽ chỉ trả về số cho các file đã tìm thấy kết quả trùng khớp:

ack -cl restrict 

Doxyfile:3 vim-license.txt:5 clint.py:1 test/unit/formatc.lua:1 src/nvim/main.c:4 src/nvim/ex_cmds.c:5 src/nvim/misc1.c:1 . . . 

Như bạn thấy , tất cả các dòng kết thúc bằng "0" đã được lược bỏ khỏi kết quả .

Nếu bạn muốn xem cột được tìm thấy trong một dòng, bạn có thể yêu cầu ack in thông tin đó bằng tùy chọn --column :

<pre>
ack -w –column –python hạn chế
</pre>
<pre>
clint.py
107: <span class = “highlight”> 31 </span>: Chỉ định một số 0-5 để <span class = “highlight”> hạn chế </span> lỗi ở một số mức độ chi tiết nhất định.
</pre>

Số thứ hai được đưa ra là số cột nơi ký tự đầu tiên của trận đấu xuất hiện. Một số editor cho phép bạn chuyển đến một dòng và cột cụ thể, điều này rất hữu ích.

Ví dụ: nếu bạn mở file client.py bằng editor vim , bạn có thể đi đến vị trí chính xác của kết quả khớp bằng lệnh 107G để đến dòng, sau đó 31| để đến vị trí cột. Loại định vị chính xác này có thể thực sự hữu ích, đặc biệt nếu bạn đang tìm kiếm một chuỗi con chung trong các từ lớn hơn.

Nếu bạn cần thêm ngữ cảnh cho kết quả, bạn có thể yêu cầu ack in ra các dòng trước hoặc sau khi trận đấu xảy ra. Ví dụ: để in ra 5 dòng trước khi khớp "giới hạn" trong file python, ta có thể sử dụng cờ -B như sau:

<pre>
ack -w –python -B 5 hạn chế
</pre>
<pre>
102- kết quả = vs7
103- Theo mặc định, kết quả được định dạng để dễ dàng phân tích cú pháp emacs. Visual Studio
104- kết quả tương thích (vs7) cũng được dùng . Các định dạng khác không được hỗ trợ.
105-
106- tiết = #
107: Chỉ định một số 0-5 để <span class = “highlight”> hạn chế </span> lỗi ở các mức độ chi tiết nhất định.
</pre>

Bạn có thể chỉ định số dòng ngữ cảnh sau trận đấu với cờ -A :

<pre>
ack -w –python -A 2 hạn chế
</pre>
<pre>
107: Chỉ định một số 0-5 để <span class = “highlight”> hạn chế </span> lỗi ở các mức độ chi tiết nhất định.
108-
109- bộ lọc = -x, + y,…
</pre>

Bạn có thể chỉ định một đặc tả ngữ cảnh cho mục đích chung sẽ in một số dòng ở trên và dưới các kết quả phù hợp với cờ -C . Ví dụ: để có 3 dòng ngữ cảnh theo một trong hai hướng, hãy nhập:

<pre>
ack -w –python -C 3 hạn chế
</pre>
<pre>
104- kết quả tương thích (vs7) cũng được dùng . Các định dạng khác không được hỗ trợ.
105-
106- tiết = #
107: Chỉ định một số 0-5 để <span class = “highlight”> hạn chế </span> lỗi ở các mức độ chi tiết nhất định.
108-
109- bộ lọc = -x, + y,…
110- Chỉ định danh sách bộ lọc danh mục được phân tách bằng dấu phẩy để áp dụng: only
</pre>

Để chỉ in các file có các file trùng khớp, thay vì in chính các file trùng khớp, bạn có thể sử dụng cờ -f :

ack -f --python 

clint.py contrib/YouCompleteMe/ycm_extra_conf.py 

Ta có thể làm điều tương tự, nhưng cũng chỉ định một mẫu cho cấu trúc file / folder bằng cách sử dụng cờ -g . Ví dụ: ta có thể tìm kiếm tất cả các file ngôn ngữ C có mẫu "log" ở đâu đó trong đường dẫn của chúng bằng lệnh :

ack -g log --cc 

src/nvim/log.h src/nvim/log.c 

Làm việc với các loại file

Ta đã thấy những điều cơ bản về cách lọc theo loại file . Ta có thể yêu cầu ack chỉ cho ta xem các file ngôn ngữ C bằng lệnh :

ack -f --cc 

test/includes/pre/sys/stat.h src/nvim/log.h src/nvim/farsi.h src/nvim/main.c src/nvim/ex_cmds.c src/nvim/os/channel.c src/nvim/os/server.c . . . 

Bạn có thể xem tất cả các ngôn ngữ mà ack biết cũng như các phần mở rộng và thuộc tính file mà nó liên kết với từng danh mục bằng lệnh :

ack --help-types 

Usage: ack-grep [OPTION]... PATTERN [FILES OR DIRECTORIES]  The following is the list of filetypes supported by ack-grep.  You can specify a file type with the --type=TYPE format, or the --TYPE format.  For example, both --type=perl and --perl work.  Note that some extensions may appear in multiple types.  For example, .pod files are both Perl and Parrot.      --[no]actionscript .as .mxml     --[no]ada          .ada .adb .ads     --[no]asm          .asm .s     --[no]asp          .asp . . . 

Như bạn thấy , điều này cung cấp cho bạn các tham số phù hợp cho từng loại file . Bạn cũng có thể yêu cầu ack loại trừ các file thuộc một danh mục nhất định bằng cách đặt trước một loại bằng “no” .

Vì vậy, ta có thể thấy số lượng file ngôn ngữ C mà ta có bằng lệnh :

ack -f --cc | wc -l 

191 

Và ta có thể làm ngược lại để xem số lượng file không phải ngôn ngữ C bằng lệnh :

ack -f --nocc | wc -l 

306 

Điều gì sẽ xảy ra nếu ta muốn sửa đổi phân loại kiểu? Ví dụ: điều gì sẽ xảy ra nếu ta muốn đối sánh các .sass , .scss.less khi ta đang tìm kiếm các file CSS. Ta có thể thấy rằng những thứ này đã được khớp trong danh mục loại “sass” và loại “less”, nhưng ta cũng có thể thêm chúng vào danh mục CSS nếu muốn.

Để làm điều này, ta có thể sử dụng cú pháp chung sau:

<pre>
ack –type-add = TYPE: FILTER: ARGS
</pre>

Lệnh --type-add thêm các luật đối sánh bổ sung cho một TYPE được chỉ định. FILTER trong trường hợp này là ext , nghĩa là khớp theo đuôi file . Sau đó, ta có thể cho nó biết rằng ta muốn thêm các phần mở rộng bổ sung đó.

Lệnh đầy đủ sẽ giống như sau:

ack --type-add=css:ext:sass,scss,less 

Tuy nhiên, điều này chỉ áp dụng cho lệnh hiện tại (không thực hiện bất kỳ tìm kiếm nào). Ta có thể thêm tìm kiếm bằng lệnh :

ack --type-add=css:ext:sass,scss,less -f --css 

Kết quả sẽ trả về các file nào kết thúc bằng .css , .sass , .scss.less . Không xảy ra các file nào trong số này trong dự án của ta . Dù bằng cách nào thì lệnh này cũng không hữu ích lắm vì nó chỉ tồn tại cho lệnh hiện tại. Bạn có thể đặt nó vĩnh viễn bằng cách thêm nó vào file ~/.ackrc của bạn:

echo "--type-add=css:ext:sass,less" >> ~/.ackrc 

Nếu ta muốn tạo một kiểu hoàn toàn mới, ta sẽ sử dụng tùy chọn --type-set để thay thế. Cú pháp hoàn toàn giống nhau, điểm khác biệt duy nhất là nó được sử dụng để xác định một kiểu không tồn tại.

Như bạn có thể đã thu thập được, TYPE từ đặc tả cú pháp ban đầu của ta chỉ là tên danh mục. FILTER mà ta thấy là phần mở rộng file , nhưng ta cũng có thể sử dụng các bộ lọc khác.

Ta có thể khớp trực tiếp tên file bằng cách sử dụng bộ lọc is . Để tạo một kiểu gọi là example trùng với file có tên example.txt , ta có thể thêm loại này vào file ~/.ackrc của ta :

--type-set=example:is:example.txt 

Ta cũng có thể xác định kết quả phù hợp với biểu thức chính quy thông thường bằng cách sử dụng bộ lọc match . Ví dụ: nếu ta muốn tạo một kiểu gọi là “bashcnf” trùng với các file “.bashrc” và “.bash_profile”, ta có thể nhập:

echo "--type-set=bashcnf:match:/.bash(rc|_profile)/" >> ~/.ackrc 

Kết luận

Như bạn thấy , ack là một công cụ rất linh hoạt để làm việc với mã nguồn lập trình. Ngay cả khi bạn chỉ sử dụng nó để tìm các file trong môi trường Linux của bạn , hầu hết thời gian, sức mạnh tăng lên của ack sẽ rất hữu ích.

<div class = “author”> Bởi Justin Ellingwood </div>


Tags:

Các tin liên quan

Cách cài đặt và sử dụng Graphite trên server Ubuntu 14.04
2014-05-27
Cách sử dụng BitTorrent Sync để đồng bộ hóa các thư mục trong Ubuntu 14.04
2014-05-19
Cách sử dụng HAProxy làm bộ cân bằng tải lớp 4 cho server ứng dụng WordPress trên Ubuntu 14.04
2014-05-16
Cách sử dụng kpcli để quản lý tệp mật khẩu KeePass2 trên server Ubuntu 14.04
2014-05-16
Cách khởi chạy trang web của bạn trên server Ubuntu 14.04 mới với LAMP, SFTP và DNS
2014-05-13
Cách cài đặt Node.js trên server Ubuntu 14.04
2014-05-12
Cách bảo vệ SSH bằng Fail2Ban trên Ubuntu 14.04
2014-05-07
Cách bảo vệ SSH bằng Fail2Ban trên Ubuntu 14.04
2014-05-07
Cách cài đặt ISPConfig3 trên server Ubuntu 14.04
2014-05-05
Cách cài đặt và sử dụng Memcache trên Ubuntu 14.04
2014-05-01