PowerShell to remove text from a string - string

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

Related

Powershell multiple string replacement using while cycle

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!

PowerShell, parsing, problem using a specific string with -match/-like and -split

I have a variable that is filled with several lines of text and I am trying to parse the data from it. Now around the middle of the text is a specific string "Reference(s) :" and I need to get everything from above this specific string. However every way I have tried has failed.
I tried making it a delimiter
$Var.split("Reference(s) :")
I tried the below 2 options just to try to capture that one line (because if I can do this, then I know I can pull everything before it).
$Var.split("`n") | Where-Object {$_ -match "Reference(s) :"}
and
$Var.split("`n") | Where-Object {$_ -like "*Reference(s) :*"}
and I've tried some if statements (Where $_ is a single line of text)
If ($_ -like "*Reference(s) :*") {some logic}
I cannot just match "Reference" because that word appears elsewhere in the text....and I am needing this to process several instances of this text.
I think the problem has to do with the parenthesis, the space, and the colon (special characters). I did try preceding each special character with a ` but that did not seem to work.
Anyone have any ideas? There has to be a way to match special characters, I just haven't found it yet.
If $var is truly a single string, you can use -split at your reference point and then retrieve the first split string ([0]). This will retrieve everything from the start of the string until the split point.
($Var -split 'Reference\(s\) :')[0]
Since -split uses regex matching, you must backslash escape regex special characters to match them literally. Here ( and ) are special.
In the future, you can just process your match string using [regex]::Escape('String'), and it will do all the escaping for you.
If you want the line just before the reference point, you can convert your string into an array. Then return the line above the matching line.
foreach ($line in ($Var -split '\r?\n')) {
if ($line -match 'Reference\(s\) :') {
$lastLine
} else {
$lastLine = $line
}
}
Apologies I know this is very similar to AdminOfThings good answer. I was already testing it so figured I'd post.
$text =
#"
Line1
Line2
Line3
Line4
Line5
Reference(s) :
Line5
Line7
Line8
Line9
Line10
"#
($text -Split "Reference\(s\) :")[0]
This also works, but for various reasons it's recommended to stay with the PowerShell native split operator:
$text.Split([String[]]"Reference(s) :", [StringSplitOptions]::None )[0]
Here it is using the where method. You can just use -eq instead of -match if that's the whole line.
get-content file
before1
before2
before3
Reference(s) :
after1
after2
after3
(get-content file).where({$_ -match [regex]::escape('Reference(s) :')},'Until')
before1
before2
before3

-replace (value) with an escape char?

I need to pull first and last names from accounts that were very poorly named from the previous IT administrator and recreate them in the same source OU.
There are characters in the account name I that I cant seem to get past. I need to pull First,Last and the remaining DN so I can recreate the account in the same OU structure without. For testing I'm only using one user in one OU, but there will be many different OU structures. "\" and "(Vendor)" are causing
My end goal is to feed the script a list of Accounts DN and recreate the account without the undesired "\" and "(vendor)" and do first.last or some variation of that.
$source = "CN=last\, first (Vendor),OU=vendors,DC=somecompany,DC=com"
$arg = "(vendor)"
($source -split ',*..=')[1].Remove($arg)
I've also tried
($source -split ',*..=')[1] -replace "`(Vendor)'", ""
The brackets and \ seem to cause everything I've tried to fail. I've searched and there doesnt seem to be a simple escape char like ^ for Batch files.
The backtick is the escape character usually for just powershell code. In the regex though, you will want to double your backslashes.
$source = "CN=last\, first (Vendor),OU=vendors,DC=somecompany,DC=com","CN=last\, first (Vendor),OU=vendors,DC=somecompany,DC=com"
$r = ($source[0] -split ',*..=|\\,').Replace("(Vendor)","").Where({ $_ -ne ''})
$r
For .remove() the argument is supposed to be a number, the number or characters to display of a string (and removing every character after the number of characters you give specify). Feeding it a string when it's expecting an int will just error so I used .replace() instead.
.remove() takes a number as an argument:
($source -split ',*..=')[1].Remove
OverloadDefinitions
-------------------
string Remove(int startIndex, int count)
string Remove(int startIndex)
Using backslashes to escape regex characters:
($source -split ',*..=')[1] -replace "\(Vendor\)", ""
last\, first
Confirmed by
[regex]::escape("(Vendor)")
\(Vendor\)
Thanks for all of the help.
$source = "CN=Doe\, John (Vendor),OU=vendors,DC=somecompany,DC=com"
$r = ($source -split ',*..=|\\,').Replace("(Vendor)","").Where({ $_ -ne ''})
$first = $r[1].replace(" ","")
$last = $r[0].replace(" ","")
$DN = ($source -split "OU=",2)[1]
$DN = "OU=" + $DN
$first
$last
$DN

Drop (substract) last n characters from a variable string length

I need to drop (or replace to nothing) last n characters of a string in powershell code. The variant could be with substraction string form a string (didn't find my answer).
I have something like this (string):
something/something/../lastsomething/NAME
where NAME is a variable text I can extract beforehand and manipulate ($name or $name.length). And the whole string can be counted - $string.length.
How can I substract this NAME from a string ($string)? I've searched many ways, including trim,replace,substring - but all of these mostly work with static words or regex, or with the begining of a string.
I need to get this:
something/something/../lastsomething
I've tried even such constructions:
$string.split('($NAME)')[0]
and
$string.split('[string]($NAME)')[0]
and other with get-AD* functions with join to bypass the strings, but nothing did the trick.
A simple solution is take the substring from beginning (0) to the last occurence of /.
$t = 'something/something/../lastsomething/NAME'
$t.Substring(0, $t.LastIndexOf('/'))
EDIT from your comment the real question is how to get
-replace '($_.Name)',' '
working. The single quotes don't expand variables - so use double quotes.
To force evaluation of $_.Name you have to enclose it with $()
-replace "/$($_.Name)"
With an unknown last element /Name
> $String = 'something/something/../lastsomething/NAME'
> $String.Split('/')[-1]
NAME
> $string = $string -replace "/$($String.Split('/')[-1])"
> $string
something/something/../lastsomething
A much simpler solution is :
> Split-Path $string
something\something\..\lastsomething
> Split-Path $string -Leaf
NAME
but it changes slashes to backslashes
You can replace it with '' (nothing ... empty string) and because -replace works with regular expressions you can make sure that you only get a "match" at the end of the string like this:
$var = '/NAME'
'something/Name/something/../lastsomething/NAME' -replace "$var$",''

Powershell removing characters from string up to last separator

I have a string
Projects\TestEnvironment\11111xx\1111111
and need to get 1111111 from it. What I'm doing now is:
$name = $dir.Substring($dir.IndexOf('\')+1)
where $dir is my string, however it only removes up to first string, is it possible to change direction?
What about using split-path?
$string = 'Projects\TestEnvironment\11111xx\1111111'
Split-Path $string -Leaf
returns 1111111.
Note the -Leaf parameter indicates that this cmdlet returns only the last item or container in the path.
#Robin's answer is good if the string is always a path (separated with "\"); in the general case, where the delimiter may be a different character, you can use
$string = "This-is-a-string-with-delimiters"
$lastword = ($string -split "-")[-1]
The -split operator defaults to splitting on a space, but will split on any character you choose to pass it, returning an array of strings, each string being the material before/between/after delimiters - in the example above, each word would be in a separate string in the array. Negative subscripts to an array count from the end of the array rather than the start, and are 1-origin rather than 0-origin - so $x[-1] is the last element of the array $x.
This technique also works on paths;
$path = "C:\Users\JSmith\Documents\Resume.doc"
$filename = ($path -split "\\")[-1]
will give you $filename -eq Resume.doc. Note that the delimiter passed to -split in this case is escaped, because the delimiter can be a regular expression, and the backslash ("\") is meaningful in regular expressions (it's the character that indicates that another meaningful character is to be "escaped", or its meaning ignored).
other solution
('Projects\TestEnvironment\11111xx\1111111' -split '\\')[-1]
or
'Projects\TestEnvironment\11111xx\1111111'.Split('\')[-1]

Resources