I have found many ways in Powershell to capture the sections of strings using split(), but I am stumped on this one. Using the example string below:
"Monkey/Zebra/Bird/Bird"
I am able to capture the end "Bird" using the code below:
$path = "Monkey/Zebra/Bird/Bird"
$animal = $path.split("/")[-1]
My end goal is to be able to capture the front of the string, without the last "split", so to output:
"Monkey/Zebra/Bird"
The number of "Animals" will vary, so I cannot hard code the number of characters or "/" to look for.
Using a regular expression with -replace:
$text = "Monkey/Zebra/Bird/Bird"
$text -replace '/[^/]+$'
Monkey/Zebra/Bird
I would probably use a regex too, but if you wanted to use a split:
("Monkey/Zebra/Bird/Bird" -split '/')[0..((("Monkey/Zebra/Bird/Bird" -split '/').count)-2)] -join '\'
I love Perl...errr Powershell
You could use a for each command such as
$path = "Monkey/Zebra/Bird/Bird"
foreach($animal in $path.split("/"))
{
Write-Host $animal
}
This will then split the path and process each animal in turn
I preface this with the fact that RegEx is probably your fastest answer. That said...
Another approach, using split, to get only one of each animal since your example was parsing out the duplicate "bird" from "Monkey/Zebra/Bird/Bird"
$Animals = "Monkey/Zebra/Bird/Bird"
($Animals.Split('/')|Select -Unique) -join '/'
Or if you just want to drop the last part you can do what EBGreen suggested, split it into individual animals, count those, return all but the last one, and re-join them together.
($Animals.Split('/'))[0..($Animals.Split('/').count-2)] -join '/'
Either of those will return Monkey/Zebra/Bird but if you like the latter of the options please attribute the answer to EBGreen.
$path = "Monkey/Zebra/Bird/Bird"
$path -replace '/\w+$'
Monkey/Zebra/Bird
Related
I am trying to solve a somewhat weird problem: I need to replace strings within a raw content by strings from the same content that meet a certain matching criteria. The input data look like this:
apple-beta
apple-alpha_orange-beta
apple-alpha_orange-alpha_cherry-beta
apple-alpha_orange-alpha_kiwi-beta
apple-alpha_orange-alpha_mango-beta
abcd-alpha_efgh-beta
abcd-alpha_efgh-alpha_ijkl-beta
abcd-alpha_efgh-alpha_mnop-beta
The replacment should work as follows: look for all "-beta" strings in the content and delete all according "-alpha" strings (eg because there is "orange-beta" already => all "orange-alpha" should be deleted, because there is "apple-beta" already => all "apple-alpha" should be deleted etc.). The result would look like this:
apple-beta
_orange-beta
__cherry-beta
__kiwi-beta
__mango-beta
abcd-alpha_efgh-beta
abcd-alpha__ijkl-beta
abcd-alpha__mnop-beta
I have tried to achieve this with a number of awkward single replacements and temporary file storages as well as with a while-construction that doesn't work at all:
$whileinput = get-content -raw C:\content-input.txt
while ($whileinput -match "\w+-beta") {
$fullval = $whileinput -match "\w+-beta" -replace "-beta","-alpha"
$whileinput = $whileinput -replace '$fullval',''
}
Any help is very appreciated!
Daniel
I would find all your beta items. Then replace the corresponding alpha items.
$data = Get-Content C:\content-input.txt
$betas = ([regex]::Matches($data,'[^_]*?(?=-beta)').Value -ne '' | Foreach-Object {
[regex]::Escape($_)} ) -join '|'
$data -replace "($betas)-alpha"
Explanation:
[regex]::Matches().Value returns only the matched texts.
[^_]*? lazily matches consecutive characters that are not _. (?=-beta) is a positive lookahead for the text -beta but doesn't include the text in the match.
-ne '' is to filter out blank output.
[regex]::Escape() is not necessarily needed in this case. But it is good practice when your text may have special regex characters that you want to match literally.
$betas contains | delimited items because | is the regex OR. Using () to surround the $betas string allows one of those words to be fully matched before matching -alpha in the replacement.
Get-Content gets the entire contents of a file into a variable, so if anything in your file matches that pattern, it'll loop infinitely (because the contents of the file always match your pattern).
PowerShell is heavily based around the concept of the "pipeline" which you can use in conjunction with the Foreach-Object cmdlet to iterate over each line in a file.
I'm not quite clear on what you want the regexes to do, but I don't think the ones you have will do what you want. Try this.
Get-Content -raw C:\content-input.txt | Foreach-Object {
if($_ -match 'beta$') {
$out+=$_ -replace '\w+-alpha',''
}
}
$out | Out-File .\path-to-output.txt
$_ is the default "pipeline variable" aka the current item in the iteration - in this case the current line. Now at least your loop is working!
I got a variable that contains different strings like domainname/users/username and domainname/accounts/serviceUsers/serviceusername.
Now I want to split these strings on the last "/" so I get only the last bit (username, serviceusername).
I know how to use split when specifiying exactly on which occurance of the "/" the string should be splitted, but not generally at the last "/".
$x = 'domainname/Accounts/ServiceUsers/serviceusername'
$x.split('/')[3]
How can I achieve that?
Hope this helps
$x.split('/')[-1]
Another way. Note that -split uses regex.
'domainname/Accounts/ServiceUsers/serviceusername'-split '/' |
select -Last 1
I have a string, which I have split using the code $CreateDT.Split(" "). I now want to manipulate two separate strings in different ways. How can I separate these into two variables?
Like this?
$string = 'FirstPart SecondPart'
$a,$b = $string.split(' ')
$a
$b
An array is created with the -split operator. Like so,
$myString="Four score and seven years ago"
$arr = $myString -split ' '
$arr # Print output
Four
score
and
seven
years
ago
When you need a certain item, use array index to reach it. Mind that index starts from zero. Like so,
$arr[2] # 3rd element
and
$arr[4] # 5th element
years
It is important to note the following difference between the two techniques:
$Str="This is the<BR />source string<BR />ALL RIGHT"
$Str.Split("<BR />")
This
is
the
(multiple blank lines)
source
string
(multiple blank lines)
ALL
IGHT
$Str -Split("<BR />")
This is the
source string
ALL RIGHT
From this you can see that the string.split() method:
performs a case sensitive split (note that "ALL RIGHT" his split on the "R" but "broken" is not split on the "r")
treats the string as a list of possible characters to split on
While the -split operator:
performs a case-insensitive comparison
only splits on the whole string
Try this:
$Object = 'FirstPart SecondPart' | ConvertFrom-String -PropertyNames Val1, Val2
$Object.Val1
$Object.Val2
Foreach-object operation statement:
$a,$b = 'hi.there' | foreach split .
$a,$b
hi
there
What is the best way to remove all text in a string after a specific character? In my case "=" and after another character in my case a ,, but keep the text between?
Sample input
=keep this,
Another way to do this is with operator -replace.
$TestString = "test=keep this, but not this."
$NewString = $TestString -replace ".*=" -replace ",.*"
.*= means any number of characters up to and including an equals sign.
,.* means a comma followed by any number of characters.
Since you are basically deleting those two parts of the string, you don't have to specify an empty string with which to replace them. You can use multiple -replaces, but just remember that the order is left-to-right.
$a="some text =keep this,but not this"
$a.split('=')[1].split(',')[0]
returns
keep this
This should do what you want:
C:\PS> if ('=keep this,' -match '=([^,]*)') { $matches[1] }
keep this
This is really old, but I wanted to add my slight variation for anyone else who may stumble across this. Regular expressions are powerful things.
To keep the text which falls between the equal sign and the comma:
-replace "^.*?=(.*?),.*?$",'$1'
This regular expression starts at the beginning of the line, wipes all characters until the first equal sign, captures every character until the next comma, then wipes every character until the end of the line. It then replaces the entire line with the capture group (anything within the parentheses). It will match any line that contains at least one equal sign followed by at least one comma. It is similar to the suggestion by Trix, but unlike that suggestion, this will not match lines which only contain either an equal sign or a comma, it must have both in order.
I referenced #benjamin-hubbard 's answer above to parse the output of dnscmd for A records, and generate a PHP "dictionary"/key-value pairs of IPs and Hostnames. I strung multiple -replace args together to replace text with nothing or tab to format the data for the PHP file.
$DnsDataClean = $DnsData `
-match "^[a-zA-Z0-9].+\sA\s.+" `
-replace "172\.30\.","`$P." `
-replace "\[.*\] " `
-replace "\s[0-9]+\sA\s","`t"
$DnsDataTable = ( $DnsDataClean | `
ForEach-Object {
$HostName = ($_ -split "\t")[0] ;
$IpAddress = ($_ -split "\t")[1] ;
"`t`"$IpAddress`"`t=>`t'$HostName', `n" ;
} | sort ) + "`t`"`$P.255.255`"`t=>`t'None'"
"<?php
`$P = '10.213';
`$IpHostArr = [`n`n$DnsDataTable`n];
?>" | Out-File -Encoding ASCII -FilePath IpHostLookups.php
Get-Content IpHostLookups.php
i want to retrive the last two columns of a string
ex
$path = C:\Documents and Settings\ac62599\AC62599_SBI_Release_2012.12.1_int\vob\SBI_src
$path = C:\views\ac62599\AC62599_view\vob\aims
output should be
\vob\SBI_src
\vob\aims
output should come like this . Thanks in advance
Use split to split the paths into directories. You can use a slice to get the last two, then use join to concatenate them back:
for my $path ('C:\Documents and Settings\ac62599\AC62599_SBI_Release_2012.12.1_int\vob\SBI_src',
'C:\views\ac62599\AC62599_view\vob\aims') {
print '\\', join('\\', (split/\\/, $path)[-2, -1]), "\n";
}
A regex seems to be the simplest solution
my ($dir) = $path =~ /((?:\\[^\\]+){2})$/;
Which is to say, look for backslash, followed by one or more non-backslash characters, and look for this sequence twice at the end of the string and capture it.
Note the use of parentheses around the variable is required to give the regex list context.
Output for the sample paths:
\vob\SBI_src
\vob\aims
$string=~m/.*(\\[^\\]*\\[^\\]*)/g;print $1