Why is the end-of-line $ anchor not working with the grep command, even though the front-of-line ^ anchor is

grepnewlines

Very new to UNIX but not new to programming. Using Terminal on MacBook. For the purposes of managing and searching word lists for crossword construction, I'm trying to get handy with the Grep command and its variations. Seems pretty straightforward but getting hung up early on with what I thought should be a simple case.

When I enter

grep "^COW" masternospaces.txt

I get what I want: a list of all the words starting with COW.

But when I enter

grep "COW$" masternospaces.txt

I expect to get a list of words ending with COW (there are many such words), and nothing is returned at all.

The file is a plain text file, with every line just a word (or a word phrase with no spaces) in all caps.

Any idea what could be happening here?

Best Answer

As @steeldriver mentionned, the problem is likely to be caused by a different line ending style than what grep is expecting.

To check the line endings

You can use hexdump to check exactly how your line endings are formatted. I suggest you use my favorite format :

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

With the output, check the line endings : 0a -> LF, 0d -> CR. A very quick example would give something like this :

$ 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..

Note the line endings in dos format : 0d 0a.

To change the line endings

You can see here or here for various methods of changing line endings using various tools, but for a one-time thing, you could always use vi/vim :

vim masternospaces.txt
:set fileformat=unix
:wq

To grep without changing anything

If you just want grep to match no matter the line ending, you could always specify line endings like this :

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

If a blank line is shown, you can check that you indeed matched something by using the -v option of cat :

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

My personal favorite

You could also both grep and standardize the output using sed :

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

where ^M is obtained by typing Ctrl-V Ctrl-M on your keyboard.

Hope this helps!

Related Question