Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -295,10 +295,18 @@ internal MatchInfo Clone()
/// <summary>
/// A cmdlet to search through strings and files for particular patterns.
/// </summary>
[Cmdlet(VerbsCommon.Select, "String", DefaultParameterSetName = "File", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=113388")]
[OutputType(typeof(MatchInfo), typeof(bool))]
[Cmdlet(VerbsCommon.Select, "String", DefaultParameterSetName = ParameterSetFile, HelpUri = "https://go.microsoft.com/fwlink/?LinkID=113388")]
[OutputType(typeof(bool), typeof(MatchInfo), ParameterSetName = new[] { ParameterSetFile, ParameterSetObject, ParameterSetLiteralFile })]
[OutputType(typeof(string), ParameterSetName = new[] { ParameterSetFileRaw, ParameterSetObjectRaw, ParameterSetLiteralFileRaw })]
public sealed class SelectStringCommand : PSCmdlet
{
private const string ParameterSetFile = "File";
private const string ParameterSetFileRaw = "FileRaw";
private const string ParameterSetObject = "Object";
private const string ParameterSetObjectRaw = "ObjectRaw";
private const string ParameterSetLiteralFile = "LiteralFile";
private const string ParameterSetLiteralFileRaw = "LiteralFileRaw";

/// <summary>
/// A generic circular buffer.
/// </summary>
Expand Down Expand Up @@ -972,7 +980,8 @@ void IContextTracker.TrackEOF()
/// <summary>
/// Gets or sets the current pipeline object.
/// </summary>
[Parameter(ValueFromPipeline = true, Mandatory = true, ParameterSetName = "Object")]
[Parameter(ValueFromPipeline = true, Mandatory = true, ParameterSetName = ParameterSetObject)]
[Parameter(ValueFromPipeline = true, Mandatory = true, ParameterSetName = ParameterSetObjectRaw)]
[AllowNull]
[AllowEmptyString]
public PSObject InputObject
Expand All @@ -995,15 +1004,17 @@ public PSObject InputObject
/// Gets or sets files to read from.
/// Globbing is done on these.
/// </summary>
[Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "File")]
[Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = ParameterSetFile)]
[Parameter(Position = 1, Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = ParameterSetFileRaw)]
[FileinfoToString]
public string[] Path { get; set; }

/// <summary>
/// Gets or sets literal files to read from.
/// Globbing is not done on these.
/// </summary>
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "LiteralFile")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = ParameterSetLiteralFile)]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = ParameterSetLiteralFileRaw)]
[FileinfoToString]
[Alias("PSPath", "LP")]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
Expand All @@ -1019,6 +1030,15 @@ public string[] LiteralPath

private bool _isLiteralPath;

/// <summary>
/// Gets or sets a value indicating if only string values containing matched lines should be returned.
/// If not (default) return MatchInfo (or bool objects, when Quiet is passed).
/// </summary>
[Parameter(Mandatory = true, ParameterSetName = ParameterSetObjectRaw)]
[Parameter(Mandatory = true, ParameterSetName = ParameterSetFileRaw)]
[Parameter(Mandatory = true, ParameterSetName = ParameterSetLiteralFileRaw)]
public SwitchParameter Raw { get; set; }

/// <summary>
/// Gets or sets a value indicating if a pattern string should be matched literally.
/// If not (default) search using pattern as a Regular Expression.
Expand All @@ -1036,7 +1056,9 @@ public string[] LiteralPath
/// Gets or sets a value indicating if the cmdlet will stop processing at the first successful match and
/// return true. If both List and Quiet parameters are given, an exception is thrown.
/// </summary>
[Parameter]
[Parameter(ParameterSetName = ParameterSetObject)]
[Parameter(ParameterSetName = ParameterSetFile)]
[Parameter(ParameterSetName = ParameterSetLiteralFile)]
public SwitchParameter Quiet { get; set; }

/// <summary>
Expand Down Expand Up @@ -1168,7 +1190,10 @@ public string[] Exclude

private int _postContext = 0;

private IContextTracker GetContextTracker() => (_preContext == 0 && _postContext == 0) ? _noContextTracker : new ContextTracker(_preContext, _postContext);
// When we are in Raw mode or pre- and postcontext are zero, use the _noContextTracker, since we will not be needing trackedLines.
private IContextTracker GetContextTracker() => (Raw || (_preContext == 0 && _postContext == 0))
? _noContextTracker
: new ContextTracker(_preContext, _postContext);

// This context tracker is only used for strings which are piped
// directly into the cmdlet. File processing doesn't need
Expand Down Expand Up @@ -1433,8 +1458,14 @@ private bool FlushTrackerQueue(IContextTracker contextTracker)
return false;
}

// If -quiet is specified but not -list return true on first match
if (Quiet && !List)
if (Raw)
{
foreach (MatchInfo match in contextTracker.EmitQueue)
{
WriteObject(match.Line);
}
}
else if (Quiet && !List)
{
WriteObject(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,24 @@ Describe "Select-String" -Tags "CI" {
}

it "Should return an array of non matching strings when the switch of NotMatch is used and the string do not match" {
$testinputone | Select-String -Pattern "goodbye" -NotMatch | Should -Be "hello", "hello"
$testinputone | Select-String -Pattern "goodbye" -NotMatch | Should -BeExactly "hello", "Hello"
}

it "Should return the same as NotMatch" {
$firstMatch = $testinputone | Select-String -pattern "goodbye" -NotMatch
$secondMatch = $testinputone | Select-String -pattern "goodbye" -n

$equal = @(Compare-Object $firstMatch $secondMatch).Length -eq 0
$equal | Should -Be True
$equal | Should -BeTrue
}

It "Should return a string type when -Raw is used" {
$result = $testinputtwo | Select-String -Pattern "hello" -CaseSensitive -Raw
$result | Should -BeOfType "System.String"
}

It "Should return ParameterBindingException when -Raw and -Quiet are used together" {
{ $testinputone | Select-String -Pattern "hello" -Raw -Quiet -ErrorAction Stop } | Should -Throw -ExceptionType ([System.Management.Automation.ParameterBindingException])
}
}

Expand Down Expand Up @@ -106,13 +115,13 @@ Describe "Select-String" -Tags "CI" {
It "Should return the name of the file and the string that 'string' is found if there is only one lines that has a match" {
$expected = $testInputFile + ":1:This is a text string, and another string"

Select-String $testInputFile -Pattern "string" | Should -Be $expected
Select-String $testInputFile -Pattern "string" | Should -BeExactly $expected
}

It "Should return all strings where 'second' is found in testfile1 if there is only one lines that has a match" {
$expected = $testInputFile + ":2:This is the second line"

Select-String $testInputFile -Pattern "second"| Should -Be $expected
Select-String $testInputFile -Pattern "second"| Should -BeExactly $expected
}

It "Should return all strings where 'in' is found in testfile1 pattern switch is not required" {
Expand All @@ -121,10 +130,10 @@ Describe "Select-String" -Tags "CI" {
$expected3 = "This is the third line"
$expected4 = "This is the fourth line"

(Select-String in $testInputFile)[0].Line | Should -Be $expected1
(Select-String in $testInputFile)[1].Line | Should -Be $expected2
(Select-String in $testInputFile)[2].Line | Should -Be $expected3
(Select-String in $testInputFile)[3].Line | Should -Be $expected4
(Select-String in $testInputFile)[0].Line | Should -BeExactly $expected1
(Select-String in $testInputFile)[1].Line | Should -BeExactly $expected2
(Select-String in $testInputFile)[2].Line | Should -BeExactly $expected3
(Select-String in $testInputFile)[3].Line | Should -BeExactly $expected4
(Select-String in $testInputFile)[4].Line | Should -BeNullOrEmpty
}

Expand Down Expand Up @@ -175,6 +184,24 @@ Describe "Select-String" -Tags "CI" {

Select-String 'matc*' $testInputFile -ca | Should -Match $expected
}

It "Should return all strings where 'in' is found in testfile1, when -Raw is used." {
$expected1 = "This is a text string, and another string"
$expected2 = "This is the second line"
$expected3 = "This is the third line"
$expected4 = "This is the fourth line"

(Select-String in $testInputFile -Raw)[0] | Should -BeExactly $expected1
(Select-String in $testInputFile -Raw)[1] | Should -BeExactly $expected2
(Select-String in $testInputFile -Raw)[2] | Should -BeExactly $expected3
(Select-String in $testInputFile -Raw)[3] | Should -BeExactly $expected4
(Select-String in $testInputFile -Raw)[4] | Should -BeNullOrEmpty
}

It "Should ignore -Context parameter when -Raw is used." {
$expected = "This is the second line"
Select-String second $testInputFile -Raw -Context 2,2 | Should -BeExactly $expected
}
}
Push-Location $currentDirectory
}