Reputation: 1001
How can I extract a substring using PowerShell?
I have this string ...
"-----start-------Hello World------end-------"
I have to extract ...
Hello World
What is the best way to do that?
Upvotes: 100
Views: 452035
Reputation: 1
Try This:
$mystring="------start---Hello World--end---------"
$result=@([regex]::split($mystring,'\-+'))[2]
$result
This frees you from having to count dashes, and instead uses a group of one or more dashes as a delimiter, and extracts the third field (the first field is null). The "@(" and ")" casts the result as an array (my paranoia more than necessity).
Upvotes: 0
Reputation: 101
Often it is easier to work with [regex] directly:
This is an alternative to -match
& $matches
building off of Matt's answer
PS> $x = "----start----Hello World----end----"
PS> $pattern = "^-*start-*(.*?)-*end-*$"
PS> $found = [regex]::Matches($x,$pattern)
PS> $found
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 0
Length : 44
Value : -----start-------Hello World------end-------
PS> $found.Groups
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 0
Length : 44
Value : -----start-------Hello World------end-------
Success : True
Name : 1
Captures : {1}
Index : 17
Length : 11
Value : Hello World
PS> $found.Groups[1].Value
Hello World
This allows us to find multiple match results in a string but we don't really need that functionality that grouping provides here so look-behind & look-ahead assertions would allow us to match without capturing groups:
PS> $x = "----start----Hello World----end----"
PS> $pattern = "(?<=-*start-*)[\w\s]*?(?=-*end-*)"
PS> [regex]::Match($x,$pattern).Value
Hello World
PowerShell & .NET regex is slightly different than vanilla regex so be sure to reference the quick reference guide for additional shortcuts.
Upvotes: 1
Reputation: 691
The Substring
method provides us a way to extract a particular string from the original string based on a starting position and length. If only one argument is provided, it is taken to be the starting position, and the remainder of the string is outputted.
PS > "test_string".Substring(0,4)
Test
PS > "test_string".Substring(4)
_stringPS >
But this is easier...
$s = 'Hello World is in here Hello World!'
$p = 'Hello World'
$s -match $p
And finally, to recurse through a directory selecting only the .txt files and searching for occurrence of "Hello World":
dir -rec -filter *.txt | Select-String 'Hello World'
Upvotes: 68
Reputation: 3350
PS> $a = "-----start-------Hello World------end-------" PS> $a.substring(17, 11) or PS> $a.Substring($a.IndexOf('H'), 11)
$a.Substring(argument1, argument2)
--> Here argument1
= Starting position of the desired alphabet and argument2
= Length of the substring you want as output.
Here 17 is the index of the alphabet 'H'
and since we want to Print till Hello World, we provide 11 as the second argument
Upvotes: 14
Reputation: 1
I needed to extract a few lines in a log file and this post was helpful in solving my issue, so i thought of adding it here. If someone needs to extract muliple lines, you can use the script to get the index of the a word matching that string (i'm searching for "Root") and extract content in all lines.
$File_content = Get-Content "Path of the text file"
$result = @()
foreach ($val in $File_content){
$Index_No = $val.IndexOf("Root")
$result += $val.substring($Index_No)
}
$result | Select-Object -Unique
Cheers..!
Upvotes: 0
Reputation: 5452
Not sure if this is efficient or not, but strings in PowerShell can be referred to using array index syntax, in a similar fashion to Python.
It's not completely intuitive because of the fact the first letter is referred to by index = 0
, but it does:
Here are some examples:
PS > 'Hello World'[0..2]
Yields the result (index values included for clarity - not generated in output):
H [0]
e [1]
l [2]
Which can be made more useful by passing -join ''
:
PS > 'Hello World'[0..2] -join ''
Hel
There are some interesting effects you can obtain by using different indices:
Forwards
Use a first index value that is less than the second and the substring will be extracted in the forwards direction as you would expect. This time the second index value is far in excess of the string length but there is no error:
PS > 'Hello World'[3..300] -join ''
lo World
Unlike:
PS > 'Hello World'.Substring(3,300)
Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within
the string.
Backwards
If you supply a second index value that is lower than the first, the string is returned in reverse:
PS > 'Hello World'[4..0] -join ''
olleH
From End
If you use negative numbers you can refer to a position from the end of the string. To extract 'World'
, the last 5 letters, we use:
PS > 'Hello World'[-5..-1] -join ''
World
Upvotes: 33
Reputation: 17492
other solution
$template="-----start-------{Value:This is a test 123}------end-------"
$text="-----start-------Hello World------end-------"
$text | ConvertFrom-String -TemplateContent $template
Upvotes: 5
Reputation: 45
Since the string is not complex, no need to add RegEx strings. A simple match will do the trick
$line = "----start----Hello World----end----"
$line -match "Hello World"
$matches[0]
Hello World
$result = $matches[0]
$result
Hello World
Upvotes: 2
Reputation: 2076
The -match
operator tests a regex, combine it with the magic variable $matches
to get your result
PS C:\> $x = "----start----Hello World----end----"
PS C:\> $x -match "----start----(?<content>.*)----end----"
True
PS C:\> $matches['content']
Hello World
Whenever in doubt about regex-y things, check out this site: http://www.regular-expressions.info
Upvotes: 81
Reputation: 809
Building on Matt's answer, here's one that searches across newlines and is easy to modify for your own use
$String="----start----`nHello World`n----end----"
$SearchStart="----start----`n" #Will not be included in results
$SearchEnd="`n----end----" #Will not be included in results
$String -match "(?s)$SearchStart(?<content>.*)$SearchEnd"
$result=$matches['content']
$result
--
NOTE: if you want to run this against a file keep in mind Get-Content returns an array not a single string. You can work around this by doing the following:
$String=[string]::join("`n", (Get-Content $Filename))
Upvotes: 8