1

Windows command line, I want to search a file for all rows starting with:

# NNN "<file>.inc"

where NNN is a number and <file> any string.

I want to use findstr, because I cannot require that the users of the script install ack.

Here is the expression I came up with:

>findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9_]*.inc" all_pre.txt

The file to search is all_pre.txt.

So far so good. Now I want to pipe that to another command, say for example more.

>findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9]*.inc" all_pre.txt | more

The result of this is the same output as the previous command, but with the file name as prefix for every row (all_pre.txt).

Then comes:

FINDSTR: cannot open |
FINDSTR: cannot open more

Why doesn't the pipe work?


snip of the content of all_pre.txt

# 1 "main.ss"
# 7 "main.ss"
# 11 "main.ss"
# 52 "main.ss"
# 1 "Build_flags.inc"
# 7 "Build_flags.inc"
# 11 "Build_flags.inc"    
# 20 "Build_flags.inc"
# 45 "Build_flags.inc(function a called from b)"

EDIT: I need to escape the dot in the regex also. Not the issue, but worth to mention.

>findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9_]*\.inc" all_pre.txt

EDIT after Frank Bollack:

>findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9_]*\.inc.*" all_pre.txt | more

is not working, although (I think) it should look for the same string as before then any character any number of times. That must include the ", right?

Gauthier
  • 40,309
  • 11
  • 63
  • 97
  • note: the return text might be a bit different, since my OS is not in english. `cannot open` is the best translation I could make myself, I don't know exactly what that would be on a real english OS. – Gauthier Apr 29 '10 at 12:09

4 Answers4

3

You are missing a trailing \" in your search pattern.

findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9]*.inc\"" all_pre.txt | more

The above works for me.

Edit:

findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9]*\.inc.*\"" all_pre.txt | more

This updated search string will now match these lines from your example:

# 1 "Build_flags.inc"
# 7 "Build_flags.inc"
# 11 "Build_flags.inc"
# 20 "Build_flags.inc"
# 45 "Build_flags.inc(function a called from b)"

Edit:

To circumvent this "bug" in findstr, you can put your search into a batch file like this:

@findstr /r /c:"^# [0-9][0-9]* \"[a-zA-Z0-9_]*\.inc" %1

Name it something like myfindstr.bat and call it like that:

myfinsdtr all_pre.txt | more

You can now use the pipe and redirection operators as usual.

Hope that helps.

Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • am I? It does make a difference, but I don't know why. I did not plan to include the closing double-quote in the regex. findstr must also find rows of the form `# 123 "file.inc(other information)"`. – Gauthier Apr 29 '10 at 14:13
  • Note also that the `findstr` command without pipe (and without trailing `\"`) does output the correct rows. – Gauthier Apr 29 '10 at 14:17
  • @Gauthier: I couldn't find any reference explaining this oddity, but it seams as if `findstr` always expects balanced quotes in the search string. – Frank Bollack Apr 29 '10 at 16:00
  • @Frank: I agree with you, and I don't seem to be alone: http://www.serverforumz.com/FINDSTR-search-couble-quote-redirect-pipe-output-ftopict25287.html – Gauthier Apr 30 '10 at 07:23
  • Thanks for the updated string. Although it would work in my case, it means that findstr would not work for `# 123 "filefilefile.inc(other info)` without the closing double quote. Somebody should be ashamed. – Gauthier Apr 30 '10 at 07:25
  • Thanks for the effort. I don't think I'll be willing to create a batch file everytime I need to search for an unbalanced pair of double quotes. I think I'll try to promote the use of GnuWin32 at work instead. – Gauthier May 03 '10 at 08:43
  • @Gauthier looks like with grep, quotes have to be balanced too! so then it looks like the same bug http://superuser.com/questions/358550/cant-pipe-or-redirect-cygwin-grep-output – barlop Nov 17 '11 at 17:02
1

I can't really explain the why, but from my experience although findstr behaviour with fixed strings (e.g. /c:"some string") is exactly as desired, regular expressions are a different beast. I routinely use the fixed string search function like so to extract lines from CSV files:

C:\> findstr /C:"literal string" filename.csv >  output.csv

No issue there.

But using regular expressions (e.g. /R "^\"some string\"" ) appears to force the findstr output to console and can't be redirected via any means. I tried >, >>, 1> , 2> and all fail when using regular expressions. My workaround for this is to use findstr as the secondary command. In my case I did this:

C:\> type filename.csv | findstr /R "^\"some string\"" > output.csv

That worked for me without issue directly from a command line, with a very complex regular expression string. In my case I only had to escape the " for it to work. other characters such as , and . worked fine as literals in the expression without escaping.

I confirmed that the behaviour is the same on both windows 2008 and Windows 7.

EDIT: Another variant also apparently works:

C:\> findstr /R "^\"some string\"" < filename.csv > output.csv

it's the same principle as using type, but just using the command line itself to create the pipe.

intech_guy
  • 11
  • 2
0

If you use a regex with an even number of double quotes, it works perfectly. But your number of " characters is odd, redirection doesn't work. You can either complete your regex with the second quote (you can use range for this purpose: [\"\"]), or replace your quote character with the dot metacharacter.

It looks like a cmd.exe issue, findstr is not guilty.

Michael Yutsis
  • 165
  • 1
  • 6
0

Here is my find, it's related to the odd number of double quotes not redirecting from within a batch script. Michael Yutsis had it right, just didn't give an example, so I thought I would:

dataset:

    "10/19/2022 20:02:06.057","99.526755039736002573"
    "10/19/2022 20:02:07.061"," "
    "10/19/2022 20:02:08.075","85.797437749585213851"
    "10/19/2022 20:02:09.096","96.71306029796799919"
    "10/19/2022 20:02:10.107","4.0273833029566628028"

I tried using the following to find just lines that had a fractional portion of a number at the end of each line.

findstr /r /c:"\.[0-9]*\"$" file1.txt > file2.txt

(a valid regex string surrounded by quotes that has one explicit double quote in it) needed to become

findstr /r /c:"\"[0-9]*\.[0-9]*\"$"" file1.txt > file2.txt

so it could identify the entire decimal (including the explicit quotes).

I tried just adding another double quote at the end of the string ($"" ) and the command worked and generated file2.txt, but it didn't match any lines in the file, so the extra trailing double quote becomes part of the regex string, I guess, and it doesn't match anything. Including the leading double quote around the full decimal was necessary, and fine for my needs.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
jnewman
  • 31
  • 3