Skip to content

Select-String where it can return multiple lines on a match, and this seem to depend on the size of the console window. #4767

Closed

Description

@swinster

Steps to reproduce

Create a file named "logs.log"

2017-09-06T19:37:17.115+00:00 node2 2017-09-06 19:37:17,114 Level="WARNING" Name="support.pulse" Message="Irregular pulse duration detected" Duration="2.31735133001"
2017-09-06T21:20:27.829+00:00 node1 2017-09-06 21:20:27,827 Level="WARNING" Name="support.pulse" Message="Irregular pulse duration detected" Duration="6.652835013"
2017-09-06T21:21:04.163+00:00 node1 2017-09-06 21:21:02,207 Level="WARNING" Name="support.pulse" Message="Irregular pulse duration detected" Duration="2.33411307697"

Now I run (I would usually use a complex RegEx pattern to match, but this is added for simpicity):

Get-Content logs.log | Select-String -Pattern '6.6' | Out-File out.txt

Expected behavior

I would expect that in all cases, I get a file with one line

2017-09-06T21:20:27.829+00:00 node1 2017-09-06 21:20:27,827 Level="WARNING" Name="support.pulse" Message="Irregular pulse duration detected" Duration="6.652835013"

Actual behavior

Depending on the size of the console window when the command is run will depend on the number of lines in the file. If I run the console maximise (and on this system, I am running a 1920x1200 display, 100% font scaling), I get the desired result. However, if I window the console and run, I could get something like

2017-09-06T21:20:27.829+00:00 node1 2017-09-06 21:20:27,827 Level="WARNING" Name="support.pulse" 
Message="Irregular pulse duration detected" Duration="6.652835013"

That's two separate lines

Environment data

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.16353.1000
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.16353.1000
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Activity

  1. markekraus commented on Sep 7, 2017

    @markekraus
    Contributor

    This is the documented behavior of Out-File. See the -Width parameter.

    Get-Content logs.log | Select-String -Pattern '6.6' | Set-Content out.txt

    performs the behavior you are expecting.

  2. swinster commented on Sep 7, 2017

    @swinster
    Author

    Mark Kraus (@markekraus) thanks, however, simply running

    Get-Content logs.log  | Out-File out.txt

    Yields a normal width file - all the original lines are still on one line when you run the command in a windowed console. What is the difference after the string as been piped through Select-String?

    Either way, this is confusing behaviour.

  3. markekraus commented on Sep 7, 2017

    @markekraus
    Contributor

    The difference is the type of object being processed. Select-String returns a Microsoft.PowerShell.Commands.MatchInfo (docs) where as Get-Content is returning Strings. The formatting is different.

    This also produces the expected results:

    Get-Content logs.log  | Select-String -Pattern '6.6' | %{$_.ToString()} | Out-File out.txt
    # or 
    Get-Content logs.log  | Select-String -Pattern '6.6' | %{$_.Line} | Out-File out.txt
  4. swinster commented on Sep 7, 2017

    @swinster
    Author
  5. lzybkr commented on Sep 7, 2017

    @lzybkr
    Contributor

    It may be the documented behavior of Out-File, but I don't anyone who likes this behavior.

  6. markekraus commented on Sep 7, 2017

    @markekraus
    Contributor

    Jason Shirk (@lzybkr) Kind of. The documented behavior of Out-File is "somewhat" useful for "somewhat" emulating what the console would look like with the output. Most of the behavior complaints I have personally seen are addressed by using Set-Content instead. I always just assumed the purpose of Out-File was intended for preserving formatting.

    In this particular instance, perhaps changing the default format behavior of Microsoft.PowerShell.Commands.MatchInfo makes sense (if possible). One would reasonably expect Select-String to return a String and for its output to behave like strings... even though it is documented that it returns MatchInfo or Bool.

  7. added
    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif
    on Sep 8, 2017
  8. SteveL-MSFT commented on Sep 10, 2017

    @SteveL-MSFT
    Member

    This behavior seems to break the principle of least astonishment to me.

  9. iSazonov commented on Sep 10, 2017

    @iSazonov
    Collaborator

    If we send anything as formatted output on screen how we can route the same in file? Is Out-File cmdlet designed for that? What is Out-* cmlets designed for?

  10. markekraus commented on Sep 10, 2017

    @markekraus
    Contributor

    IMO, it is Select-String that breaks the principle of least astonishment. Out-File has its purpose. Maybe the default behavior is debatable, but, that behavior is what distinguishes it from the *-Content cmdltes.

    Select-String, on the other hand, should probably be returning Strings. If it did, the formatting would not result in Out-File line-wrapping or truncating. This is not to say returning MatchInfo is not useful, just not expected as the default behavior, IMO. The name implies it selects Strings. The output behavior could be changed but I have seen code that does rely on the MatchInfo objects. That behavior would need to be preserved (possibly with a switch parameter or something).

  11. lzybkr commented on Sep 10, 2017

    @lzybkr
    Contributor

    Select-String returning a MatchInfo is definitely useful for the usual reasons returning objects is useful. Here is one example - custom formatting to highlight the match: https://gist.github.com/lzybkr/dcb973dccd54900b67783c48083c28f7

  12. markekraus commented on Sep 10, 2017

    @markekraus
    Contributor

    Jason Shirk (@lzybkr) Absolutely! That's why I originally suggested possibly modifying the default format of MatchInfo instead of switching to String. If the default format of MatchInfo behaved like String, It would behave closer to what one would expect in most situations without breaking all the many things that have been made to work with MatchInfo.

  13. mklement0 commented on Sep 12, 2017

    @mklement0
    Contributor

    The issue is not specific to Select-String (whose naming may be debatable, but there's only so much information you can cram into a cmdlet name, and it does operate on strings as input), it is fundamental to PowerShell's default output formatting:

    Unfortunately - from what I can tell, without having dug into the source - all Out-* cmdlets use the same window width-sensitive formatting, even though respecting the host's window width really only makes sense for actual host (console) output (by default or via Out-Host).

    Yes, the behavior may be documented, but as Jason Shirk (@lzybkr) and Steve Lee (@SteveL-MSFT) observe, it is undesirable / unexpected.
    This is especially true for the > redirection operator, which is effectively an alias of Out-File.

    Thus, the real fix - which is a breaking change, though hopefully a bucket 3 change - would be to remove any host window-width sensitivity from Out-* cmdlets that don't target the host (console), namely Out-File and Out-String.

    A simpler demonstration of the problem:

    # Default formatting truncates the property value and appends "..." to fit the window width.
    > [pscustomobject] @{ str = 'x' * 1024 + '!' } 
    str                                                                                                                                                                 
    ---                                                                                                                                                                 
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
    
    # Unfortunately, the same truncation happens when you use Out-File, resulting in LOSS OF DATA:
    > [pscustomobject] @{ str = 'x' * 1024 + '!' }  | out-file tmp.txt; Get-Content tmp.txt
    str                                                                                                                                                                 
    ---                                                                                                                                                                 
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...

    As an aside: There seems to be a bug with respect to using > to redirect a [pscustomobject] instance to a file - see #4812.

  14. iSazonov commented on Sep 12, 2017

    @iSazonov
    Collaborator

    If '>' is alias for Out-File can we replace it with Set-Content?

  15. markekraus commented on Sep 12, 2017

    @markekraus
    Contributor

    Unfortunately - from what I can tell, without having dug into the source - all Out-* cmdlets use the same window width-sensitive formatting, even though respecting the host's window width really only makes sense for actual host (console) output (by default or via Out-Host).

    Right, which is what I have always assumed the Out-* commands are intended for. And yes, it does make sense, IMO, to have that functionality for files as well as the console. Sometimes you want the UX captured and Out-File accomplishes that goal

    I don't see the point in making Out-File behave outwardly like Set-Content/Add-Content with a different internal implementation.

    In defense of Out-File:
    Out-File always did what I expected it to do when I was new to the language. What I saw on screen I wanted in a file and Out-File did just that. It wasn't until I was more familiar with the language and understood the "object" aspect of output (came from heavy text based languages) that I even saw this as a limitation.

  16. 17 remaining items

  17. lzybkr commented on Sep 13, 2017

    @lzybkr
    Contributor

    Years ago I tried setting the default width to int.MaxValue - in the current implementation that kinda works in some places, but in others, it turns out to be a terrible idea - you will get padding to the width you asked for.

    I do think we need to detect where the output is going - and not just for the width. If the output is to a file, we might also want to strip ansi escape sequences (with some sort of option to not do so).

    As for performance - I lost any incentive to improve the perf of Select-String after finding ripgrep. It even has an option to output in a PowerShell friendly way so it wouldn't be too hard to write a wrapper and get objects, but I haven't done that yet.

  18. iSazonov commented on Sep 14, 2017

    @iSazonov
    Collaborator

    CoreFX RegEx implementation is so bad?

  19. lzybkr commented on Sep 14, 2017

    @lzybkr
    Contributor

    I haven't compared the CLR regex to Rust's regex directly, but I'm confident we can do much better without touching the CLR's regex code.

  20. mklement0 commented on Sep 14, 2017

    @mklement0
    Contributor

    To continue on the tangent, more generally:

    The ability to call out to external utilities is important - even more so in the Unix world.
    I'm sure there are other cmdlets whose performance with large input sets will necessitate using external utilities instead.

    Conversely, other shells may want to take advantage of PowerShell's high-level features on demand, by calling PowerShell's CLI as needed.

    The interfaces to properly support these scenarios aren't quite there yet / may never get there, unfortunately:

  21. iSazonov commented on Sep 15, 2017

    @iSazonov
    Collaborator

    I went through ripgrep repo and see that it's a very young and single man's project. I saw a message that its public API should be re-designed. Also it still haven't library - I'd prefer the same way we use Newton.

    I read ripgrep perf analize. It is veryinteresting. We can benefit from that. For example, make our FileSystem provider (dir traversal) more fast. It seems again related to migration on ETS.

  22. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  23. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  24. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  25. microsoft-github-policy-service commented on Nov 23, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-No ActivityIssue has had no activity for 6 months or moreWG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions