No, -H
and -o
are not mutually exclusive. You may have a Carriage Return character in the part that is matched. This would make the following text be written at the start of the line, thus overwriting the file name.
$ printf 'foobar\n' | grep -Ho '.bar'
(standard input):obar
$ printf 'foo\rbar\n' | grep -Ho '.bar'
bar
Also, since both lines belong to the same file baz.txt
(if your example is correct), this may also be due to a long line (larger than the screen width) being wrapped to the next line.
$ printf 'foo%80sbar\n' | grep -Ho 'foo.*'
(standard input):foo
bar
Whether one of those scenarios may apply to your situation really depends on your search regex and the content of your files.
Why? because your shell interprets some special characters, such as \
in your example.
You are running into troubles because you do not protect the string that you try to pass as argument to grep via the Shell.
Several solutions:
- singlequoting the string,
- doublequoting the string (with doublequoting the shell will interpret several things, such as
$variables
, before sending the resulting string to the command),
- or not use quoting (which I strongly advise against) but add backslashes in the right places to prevent the shell to interpret the next characters before sending it to the command.
I recommend to protect the string via single quotes, as it keeps almost everything literraly:
grep '9\.0' #send those 4 characters to grep in a single argument
The Shell pass the singlequoted string literally.
Note: The only thing you can't include inside a single quoted shell string is a single quote (as this ends the singlequoting).
To include a singlequote inside a singlequoted shell string, you need to first end the singlequoting, immediately add an escaped singlequote \'
(or one between doublequotes: "'"
) and then immediately reenter the singlequoting to continue the single quoted string : for exemple to have the shell execute the command grep a'b
, you could write the parameter as 'a'\''b'
so that the shell sends a'b
to grep: so write: grep 'a'\''b'
, or grep 'a'"'"'b'
If you insist on not using quoting, you need your shell to have a \\
to have it send a \
to grep.
grep 9\\.0 # ie: a 9, a pair \\, a ., and a 0 , and the shell interprets the pair \\ into a literal \
If you use doublequotes: you need to take into account that the shell will interprets several things first ($vars
, \
, etc). for exemple when it sees an unescaped or unquoted \
, it waits the next character to decide how to interpret it. \w
is seen as a single letter w
, \\
is seen as a single letter \
, etc.
grep "9\\.0" # looks here the same as not quoting at all...
#but doublequoting allows you to have spaces, etc, inside the string
Best Answer
Type your search using / (or ?) to begin with, which will allow you to tweak your regex (since you're using incsearch)
Once you get it all nice, you can use the previous search pattern (the one you just used) in the substitute command by using two separators for the 'search' item:
Of course, you can use selections and ranges, as normal.