Here is what I have.
get-childitem "\\myfileserver\out\*" | foreach { rename-item $_ $_.Name.Replace("_123456_837P.", ".").Replace(".test.", ".sa.").Replace("_987654_837I." , ".") }
Here is the filename I want to fix
999_987654_837I.74161.test
I want to remove _987654_837I from the file name. I was just going to rename it but those numbers may change. So now I want to remove the 4th character starting at the _ and back to the "I" or 9th character.
You can use a regex pattern to get the required part.
See regex example + explanation:
https://regex101.com/r/xNoBVD/2
I use positive lookbehind to force regex to get the first 3 characters at the very beginning of the line (^) without capturing it. The following 12 characters are captured and can then be replaced with ''
$regexReplacePattern = '(?<=^.{3}).{12}'
'999_987654_837I.74161.test' -replace $regexReplacePattern, ''
Related
Lets say I have switch statement like so:
$NewName = "test.psd"
switch -RegEX ($NewName) {
"^\..*" { #if string starts with "." it means only change extension
'Entry Starts with a "."'
}
".*\..*" { # "." is in the middle , change both basename and extension
'Entry does not start with a "."'
}
"[^.]" { # if no "." at all, it means only change base name
'No "." present'
}
}
The first and second condidtions work as expected, but the last one always triggers. It will trigger against:
$NewName = "test.psd"
$NewName = ".psd"
$NewName = "test"
Doesnt regex "[^.]" mean if there is a dot, dont match. Essentially only trigger in the absence of a dot.
My expected outcome is for the last statement to only trigger if there is not dot present.
Any help on this, would be wellcome.
That would only work if "." were the only character. All the other characters would match it. You would have to repeat that pattern for every character on the line. See also Regex - Does not contain certain Characters
'a.' -match '^[^.]+$'
False
'ab' -match '^[^.]+$'
True
The dot is a special character in regular expressions, and needs to be escaped when you want to use a literal dot. Try "[^\.]" for the regular expression in the third case.
Hopefully this question isn't already answered on the site. I want to replace every number in a string with that number and a space. So here's what I have right now:
"31222829" -replace ("[0-9]","$0 ")
The [0-9] looks for any numbers, and replaces it with that character and the space. However, it doesn't work. I saw from another website to use $0 but I'm not sure what it means.The output I was looking for was
3 1 2 2 2 8 2 9
But it just gives me a blank line. Any suggestions?
LardPies
This probably isn't the right way to do it, but it works.
("31222829").GetEnumerator() -join " "
The .GetEnumerator method iterates over each character in the string
The -join operator will then join all of those characters with the " " space
tl;dr
PS> "31222829" -replace '[0-9]', '$& '
3 1 2 2 2 8 2 9
Note that the output string has a trailing space, given that each digit in the input ([0-9]) is replaced by itself ($&) followed by a space.
As for what you tried:
"31222829" -replace ("[0-9]","$0 ")
While enclosing the two RHS operands in (...) doesn't impede functionality, it's not really helpful to conceive of them as an array - just enumerate them with ,, don't enclose them in (...).
Generally, use '...' rather than "..." for the RHS operands (the regex to match and the replacement operand), so as to prevent confusion between PowerShell's string expansion (interpolation) and what the -replace operator ultimately sees.
Case in point: Due to use of "..." in the replacement operand, PowerShell's string interpolation would actually expand $0 as a variable up front, which in the absence of a variable expands to the empty string - that is why you ultimately saw a blank string.
Even if you had used '...', however, $0 has no special meaning in the replacement operand; instead, you must use $& to represent the matched string, as explained in this answer.
To unconditionally separate ALL characters with spaces:
Drew's helpful answer definitely works.
Here's a more PowerShell-idiomatic alternative:
PS> [char[]] '31222829' -join ' '
3 1 2 2 2 8 2 9
Casting a string to [char[]] returns its characters as an array, which -join then joins with a space as the separator.
Note: Since -join only places the specified separator (' ') between elements, the resulting string does not have a trailing space.
You can use a regex with positive lookahead to avoid the trailing space. Lookahead and lookbehind are zero-length assertions similar to ^ and $ that match the start/end of a line. The regex \d(?=.) will match a digit when followed by another character.
PS> '123' -replace '\d(?=.)', '$0 '
1 2 3
To verify there's no trailing space:
PS> "[$('123' -replace '\d(?=.)', '$0 ')]"
[1 2 3]
I have a .properties file in which I want to replace the string Compass with BBB. My question is : I want to extract string which is belong
name , JDBC/ , ds_name = '' , java.lang.String then I will update with a new one. BTW, data source name is not fixed its dynamic variable. Just I have written it as sample string.
I have tried the following PowerShell code:
$DName = read-host -prompt "Please Enter Database Name"
ForEach ($client in (Get-Content Clients.txt)) {
(Get-Content "\\$client\D$\Runtime\run.properties") -replace "$old database name which is extract","$DName" |
Out-File "\\$client\D$\Runtime\run.properties"
}
run.properties:
dsid = AdminTask.createDatasource(provider_id, '[-name Compass -jndiName jdbc/Compass
-dataStoreHelperClassName com.ibm.websphere.rsadapter.MicrosoftSQLServerDataStoreHelper
-componentManagedAuthenticationAlias TEMP-HRZEMM01Node01/PlatformDataSource -containerManagedPersistence true
-xaRecoveryAuthAlias TEMP-HRZEMM01Node01/PlatformDataSource -configureResourceProperties [[databaseName java.lang.String Compass] [portNumber java.lang.Integer 1433] [serverName java.lang.String SQLSVR1]]]')
AdminConfig.create('MappingModule', dsid , '[[authDataAlias TEMP-HRZEMM01Node01/PlatformDataSource] [mappingConfigAlias ""]]')
ds_name = 'Compass' #Name copied from your question, update if required
If I understand the question correctly, you would like to first find the database name (which can be anything, Compass is just an example) stored in the .properties file and if found replace that by a value entered in the console.
In that case, I think this should do it:
$newDbName = Read-Host -prompt "Please Enter Database Name"
$clientFile = "Clients.txt"
ForEach ($client in (Get-Content $clientFile)) {
$content = Get-Content "\\$client\D$\Runtime\run.properties" -Raw
# see if we can extract the database name from the file
if ($content -match '(?:-name\s+|jdbc/|databaseName java\.lang\.String\s+|ds_name = '')(?<dbname>[^\s''\]]+)') {
$oldDbName = $matches['dbname']
Write-Host "Replacing '$oldDbName' with '$newDbName' for client '$client'"
($content -replace $oldDbName, $newDbName) |
Out-File "\\$client\D$\Runtime\run.properties"
}
else {
Write-Warning "Could not parse the old database name from '\\$client\D$\Runtime\run.properties'.."
}
}
Regex explanation
(?: Match the regular expression below
Match either the regular expression below (attempting the next alternative only if this one fails)
-name Match the characters “-name” literally
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
| Or match regular expression number 2 below (attempting the next alternative only if this one fails)
jdbc/ Match the characters “jdbc/” literally
| Or match regular expression number 3 below (attempting the next alternative only if this one fails)
databaseName\ java Match the characters “databaseName java” literally
\. Match the character “.” literally
lang Match the characters “lang” literally
\. Match the character “.” literally
String Match the characters “String” literally
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
| Or match regular expression number 4 below (the entire group fails if this one fails to match)
ds_name\ =\ ' Match the characters “ds_name = '” literally
)
(?<dbname> Match the regular expression below and capture its match into backreference with name “dbname”
[^\s'\]] Match a single character NOT present in the list below
A whitespace character (spaces, tabs, line breaks, etc.)
The character “'”
A ] character
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
I have a filename and I wish to extract two portions of this and add into variables so I can compare if they are the same.
$name = FILE_20161012_054146_Import_5785_1234.xml
So I want...
$a = 5785
$b = 1234
if ($a = $b) {
# do stuff
}
I have tried to extract the 36th up to the 39th character
Select-Object {$_.Name[35,36,37,38]}
but I get
{5, 7, 8, 5}
Have considered splitting but looks messy.
There are several ways to do this. One of the most straightforward, as PetSerAl suggested is with .Substring():
$_.name.Substring(35,4)
Another way is with square braces, as you tried to do, but it gives you an array of [char] objects, not a string. You can use -join and you can use a range to make that easier:
$_.name[35..38] -join ''
For what you're doing, matching a pattern, you could also use a regular expression with capturing groups:
if ($_.name -match '_(\d{4})_(\d{4})\.xml$') {
if ($Matches[1] -eq $Matches[2]) {
# ...
}
}
This way can be very powerful, but you need to learn more about regex if you're not familiar. In this case it's looking for an underscore _ followed by 4 digits (0-9), followed by an underscore, and four more digits, followed by .xml at the end of the string. The digits are wrapped in parentheses so they are captured separately to be referenced later (in $Matches).
Yet another approach: returns 1234 substring four times.
$FileName = "FILE_20161012_054146_Import_5785_1234.xml"
# $FileName
$FileName.Substring(33,4) # Substring method (zero-based)
-join $FileName[33..36] # indexing from beginning (zero-based)
-join $FileName[-8..-5] # reverse indexing:
# e.g. $FileName[-1] returns the last character
$FileArr = $FileName.Split("_.") # Split (depends only on filename "pattern template")
$FileArr[$FileArr.Count -2] # does not depend on lengths of tokens
I am having an issue with my PowerShell Program counting the number of sentences in a file I am using. I am using the following code:
foreach ($Sentence in (Get-Content file))
{
$i = $Sentence.Split("?")
$n = $Sentence.Split(".")
$Sentences += $i.Length
$Sentences += $n.Length
}
The total number of sentences I should get is 61 but I am getting 71, could someone please help me out with this? I have Sentences set to zero as well.
Thanks
foreach ($Sentence in (Get-Content file))
{
$i = $Sentence.Split("[?\.]")
$Sentences = $i.Length
}
I edited your code a bit.
The . that you were using needs to be escaped, otherwise Powershell recognises it as a Regex dotall expression, which means "any character"
So you should split the string on "[?\.]" or similar.
When counting sentences, what you are looking for is where each sentence ends. Splitting, though, returns a collection of sentence fragments around those end characters, with the ends themselves represented by the gap between elements. Therefore, the number of sentences will equal the number of gaps, which is one less the number of fragments in the split result.
Of course, as Keith Hill pointed out in a comment above, the actual splitting is unnecessary when you can count the ends directly.
foreach( $Sentence in (Get-Content test.txt) ) {
# Split at every occurrence of '.' and '?', and count the gaps.
$Split = $Sentence.Split( '.?' )
$SplitSentences += $Split.Count - 1
# Count every occurrence of '.' and '?'.
$Ends = [char[]]$Sentence -match '[.?]'
$CountedSentences += $Ends.Count
}
Contents of test.txt file:
Is this a sentence? This is a
sentence. Is this a sentence?
This is a sentence. Is this a
very long sentence that spans
multiple lines?
Also, to clarify on the remarks to Vasili's answer: the PowerShell -split operator interprets a string as a regular expression by default, while the .NET Split method only works with literal string values.
For example:
'Unclosed [bracket?' -split '[?]' will treat [?] as a regular expression character class and match the ? character, returning the two strings 'Unclosed [bracket' and ''
'Unclosed [bracket?'.Split( '[?]' ) will call the Split(char[]) overload and match each [, ?, and ] character, returning the three strings 'Unclosed ', 'bracket', and ''