Tại sao neo $ cuối dòng không hoạt động với lệnh grep, mặc dù neo phía trước ^ là gì?


19

Rất mới đối với UNIX nhưng không mới đối với lập trình. Sử dụng Terminal trên MacBook. Với mục đích quản lý và tìm kiếm danh sách từ để xây dựng ô chữ, tôi đang cố gắng làm quen với lệnh Grep và các biến thể của nó. Có vẻ khá đơn giản nhưng bị treo lên sớm với những gì tôi nghĩ nên là một trường hợp đơn giản.

Khi tôi vào

grep "^COW" masternospaces.txt

Tôi nhận được những gì tôi muốn: một danh sách tất cả các từ bắt đầu bằng COW.

Nhưng khi tôi vào

grep "COW$" masternospaces.txt

Tôi hy vọng sẽ có được một danh sách các từ kết thúc bằng COW (có rất nhiều từ như vậy) và không có gì được trả lại cả.

Tệp này là một tệp văn bản đơn giản, với mỗi dòng chỉ là một từ (hoặc cụm từ không có khoảng trắng) trong tất cả các chữ hoa.

Bất cứ ý tưởng những gì có thể xảy ra ở đây?


3
Nguồn gốc của tệp masternospaces.txt là gì? có khả năng nó có các dòng kết thúc kiểu Windows (CR-LF) thay vì các kiểu LF của Unix không?
Steeldo

2
Không chắc chắn, nhưng bạn đang tìm kiếm một danh sách các từ hoặc một danh sách các dòng ... ?
mikeerv

Steeldo-- Một cái gì đó như thế là suy nghĩ đầu tiên của tôi. Không chắc chắn làm thế nào để kiểm tra những gì đang xảy ra ở đó, hoặc thậm chí những khả năng là gì. Giả sử rằng lợi nhuận cuối cùng là lợi nhuận cuối cùng. Tập tin đó là một bản tóm tắt lớn từ một vài nguồn. Tôi thậm chí không chắc chắn cái nào sẽ được coi là tệp gốc. Và nó đã trải qua ít nhất ba bộ xử lý văn bản trên cả máy PC và Mac. Điều gì có thể là cách tốt nhất để xem loại chấm dứt sử dụng là gì?
DTalvacchio

mikeerv-- Trong tệp .txt này, mỗi dòng chỉ là một từ (hoặc cụm từ không có khoảng cách giữa các từ, vì vậy lại là một "từ"). Vì vậy, tôi đang tìm kiếm các dòng, tôi cho rằng. . . chỉ là mỗi dòng chỉ có một trong những gì tôi đang xem xét một từ cho mục đích ô chữ.
DTalvacchio

1
Bạn có thể sử dụng hexdumpđể kiểm tra chính xác cách kết thúc dòng của bạn được định dạng. Tôi đề nghị bạn sử dụng định dạng yêu thích của tôi : hexdump -e '"%08_ad (0x%08_ax) "8/1 "%02x "" "8/1 "%02x "' -e '" "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt. Với đầu ra, kiểm tra các kết thúc dòng: 0a-> LF, 0d-> CR.
user43791

Câu trả lời:


23

Như @steel ấn đã đề cập, vấn đề có thể được gây ra bởi một kiểu kết thúc dòng khác với những gì grepđang mong đợi.

Để kiểm tra kết thúc dòng

Bạn có thể sử dụng hexdumpđể kiểm tra chính xác cách kết thúc dòng của bạn được định dạng. Tôi đề nghị bạn sử dụng định dạng yêu thích của tôi:

hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt

Với đầu ra, kiểm tra các kết thúc dòng: 0a-> LF, 0d-> CR. Một ví dụ rất nhanh sẽ đưa ra một cái gì đó như thế này:

$ hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt
00000000 (0x00000000)    4e 6f 20 43 4f 57 20 65   6e 64 69 6e 67 0d 0a 45    No COW e|nding..E
00000016 (0x00000010)    6e 64 69 6e 67 20 69 6e   20 43 4f 57 0d 0a          nding in| COW..

Lưu ý các kết thúc dòng ở định dạng dos : 0d 0a.

Để thay đổi kết thúc dòng

Bạn có thể thấy ở đây hoặc ở đây để biết các phương pháp thay đổi kết thúc dòng khác nhau bằng các công cụ khác nhau, nhưng đối với một lần, bạn luôn có thể sử dụng vi / vim:

vim masternospaces.txt
:set fileformat=unix
:wq

Để grep mà không thay đổi bất cứ điều gì

Nếu bạn chỉ muốn grepkhớp bất kể dòng kết thúc, bạn luôn có thể chỉ định kết thúc dòng như thế này:

grep 'COW[[:cntrl:]]*$' masternospaces.txt

Nếu một dòng trống được hiển thị, bạn có thể kiểm tra xem bạn thực sự khớp với thứ gì đó bằng cách sử dụng -vtùy chọn cat:

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v

Sở thích cá nhân của tôi

Bạn cũng có thể cả grep và chuẩn hóa đầu ra bằng cách sử dụng sed:

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt

nơi ^Mcó được bằng cách gõ Ctrl-V Ctrl-Mtrên bàn phím của bạn.

Hi vọng điêu nay co ich!


Đó là tất cả vô cùng hữu ích. Đã hết thời gian hôm nay nhưng sẽ xem xét kỹ tất cả những điều này vào ngày mai và xem những gì. Nếu trong lúc này, bất kỳ ai trong số bạn có một liên kết đến hướng dẫn tham khảo lệnh Unix yêu thích của bạn để tôi có thể tự dạy mình một chút về cách mọi thứ đang hoạt động, tôi sẽ đánh giá cao nó. Tôi đã chọn các mảnh ở đây và ở đó nhưng vẫn chưa tìm thấy một nguồn nào để giải thích. Cảm ơn tất cả mọi người và sẽ kiểm tra vào ngày mai với một bản cập nhật hy vọng thành công. --D
DTalvacchio

Thật tệ khi bài viết này không đóng cửa, đối với tôi ít nhất. Đối với cuộc sống của tôi, tôi không thể tìm ra làm thế nào để phù hợp với kết thúc của dòng. Nếu tôi thực hiện một kết xuất hex, tôi không thể tìm thấy một dòng kết thúc đẹp như ví dụ của bạn ở trên. Tôi không quen làm việc với hex nên có thể tôi không đọc đúng. Tôi cũng đã thử [[:cntrl:]]@ user43791 được đề xuất và nó vẫn không phù hợp với tôi. Điều này không có ý nghĩa. Tôi đang sử dụng GNU grep 2.20 và phân tích cú pháp đầu ra từ nDPI được ghi vào tệp văn bản
harperville 22/2/2016

@harperville Nếu bạn cat -v yourfile.ext, bạn thấy gì?
user43791

Vâng, không có gì để thú vị hoặc bất ngờ. Chỉ là nội dung như tôi mong đợi để xem chúng. Bất cứ điều gì cụ thể bạn đang tìm kiếm? Tôi không thể dán đầu ra ở đây nhưng tôi chỉ thấy nội dung. Thông thường ol '"văn bản tiếng Anh ASCII" theo file.
harperville 3/03/2016

@harperville Không có thêm "^ M" ở cuối mỗi dòng? Bạn có thể dán vài dòng hex đầu tiên không?
dùng43791 ngày

1

Mặc dù bạn có thể sử dụng cú pháp RegEx 'tiêu chuẩn' với grep (như trong câu trả lời của @ user43791 ), grep cũng có các định danh khác để biểu thị các ranh giới đầu vào.

Các kết quả khớp cho điểm bắt đầu và kết thúc của toàn bộ dòng là \`(backtick) (thay vì ^) và \'(dấu nháy đơn) (thay vì $).

Vì vậy, đối với lệnh ban đầu của bạn, bạn sẽ sử dụng: grep "COW\'" masternospaces.txt

Lưu ý bên lề: Điều quan trọng cũng cần lưu ý là ?+sẽ được xử lý theo nghĩa đen trừ khi bạn thoát chúng bằng cách sử dụng \?\+biến chúng thành đối tác chọn kiểu RegEx của chúng.

Nguồn: grepcú pháp biểu thức chính quy


grep đang dùng ^ (caret) để bắt đầu và \ '(dấu nháy đơn) cho kết thúc
GypsyCosmonaut

1

Một cách khác để loại bỏ \rtrước grep:

... | dos2unix | egrep 'COW$' | ...

Tôi thích điều đó rất rõ ràng vì tôi không nhớ những thứ như [[:cntrl:]]lâu dài.


-2

"COW $" khi bash đặt tham số cho grep, nó được hiểu là 'COW' trong đó coi "$" là "", vì becase $ là một simbol thoát. khi không có gì được kết hợp bởi $, nó được hiểu là chuỗi rỗng bởi bash shell, vì vậy, bạn nên sử dụng grep 'COW $' masternospaces.txt thay thế.


3
vì không có sự mở rộng hợp lệ nào $, nó sẽ bị bỏ lại một mình bởi bash và được sử dụng bởi grep. Xem cho chính mình: echo "COW$"- ý $chí vẫn còn đó.
Jeff Schaller

-3

Trong BSD grep, bạn cần thoát "$" và đặt chuỗi của bạn trong dấu ngoặc kép:

"COW\$"

1
À, không. Cái $này sẽ không đặc biệt đối với shell, bởi vì những thứ sau nó không phải là tên biến shell hợp lệ. Sử dụng dấu ngoặc đơn xung quanh chuỗi tĩnh là một ý tưởng tốt hơn, nhưng sẽ không có sự khác biệt ở đây.
Kusalananda
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.