3

In Ubuntu I'm working on a C file that was originally created under Windows and then committed to source control. Vim shows the file format is "dos", which I gather just means it has CR/LF line endings. I wanted to get a list of function definitions in the file by using grep to find the regular expression ')$', but it returned nothing. When I changed the file format to "unix" (:set ff=unix in vim) then the grep worked as expected.

Is this a bug, or does grep officially not support CR/LF line endings? I did find this on the man page:

-U --binary Treat the file(s) as binary. By default, under MS-DOS and MS-Windows, grep guesses whether a file is text or binary as described for the --binary-files option. If grep decides the file is a text file, it strips carriage returns from the original file contents (to make regular expressions with ^ and $ work correctly). Specifying -U overrules this guesswork, causing all files to be read and passed to the matching mechanism verbatim; if the file is a text file with CR/LF pairs at the end of each line, this will cause some regular expressions to fail. This option has no effect on platforms other than MS-DOS and MS-Windows.

But it does say under MS-DOS and MS-Windows in the previous sentence, so I don't know if that applies at all here?

Is there some other regular expression that should match CR/LF, or some other command-line option to grep I'm not seeing that would help? Or is the only solution really for me to create a bunch of commit-noise by reformatting my colleagues' files?

2
  • Doh - I literally found this a few seconds after posting my question: stackoverflow.com/questions/73833
    – Kisama
    Oct 13, 2015 at 11:40
  • Ubuntu is not MS-DOS or MS-Windows, so it does not apply. I'd think you'd have to grep $')\r$' to match the CR-NL line ending Oct 13, 2015 at 13:44

1 Answer 1

3

In Windows and DOS text files, each line has an extra carriage-return character at the end. This means that the regular expression )$ would not match any lines, because each line would additionally have that extra carriage-return character.

To match lines that end with ) and a carriage-return character, use )[[:space:]]$ as the expression. The [[:space:]] bit will match any single "space-like character", and this includes the carriage-return.

You may also give grep a literal carriage return in the expression, by using e.g. $')\r$' as the argument string that is the expression. In some shells, $'...' is a "C-string", and the shell will expand escape sequences in it, like \t, \r, \n etc., to the actual characters that these represent in the C programming language.

Some variants of grep may also recognize the expression \s as matching a carriage-return character (just like using the more portable [[:space:]] would).

If you are going to work with these files on a Unix system, it would be easiest to convert your files to Unix text files using the approach that you mention in your question (saving the as Unix text files from the Vim editor), or by converting them using a tool such as dos2unix.


The text saying "under MS-DOS and MS-Windows" refers to running grep on those particular operating systems. This does not apply to you as you are on Ubuntu.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .