I need to keep the first 5 characters from data being pulled from a text file.
Data looks like this:
S1831KWT0081
S2004KWT0083
S2351KWT0085
S0054KWT0087
Results should looks like this:
S1831
S2004
S2351
S0054
I can get it working when setting the variable within PowerShell:
PS> $a = "S1831KWT0081"
PS> $a.Substring(0, $a.IndexOf('K'))
S1831
but I'm stuck when trying to pull from a text file.
To solve this, you will need to parse the text file on a line-by-line basis. Basically treating each line as a value in an array.
Get-Content location.txt | foreach { $_.Substring(0, $_.IndexOf('K')) }
Another option would be a regular expression replacement:
(Get-Content 'C:\path\to\input.txt') -replace '^(.{5}).*', '$1'
That would also allow you more specific matches, e.g. like this:
$re = '^([a-z]\d{4}).*'
(Get-Content 'C:\path\to\input.txt') -match $re -replace $re, '$1'
Just to show there always is more than one PoSh way ;-)
gc .\input.txt|%{$_.split('K')[0]}
Or the more verbose version
Get-Content .\input.txt |
ForEach-Object { $_.split('K')[0] }
Related
Is there any way to name the variable for an array something in my Catch { and then have another array name for the array inside Try/script part of my function?
Cause when i try doing like this $computerObject = [PSCustomObject]#{
and then doing Write-Output $computerArray i can only get either my variables inside Try/script array being displayed inside Powershell window. Or only get the $error message from my Catch.. Is there any way to name each array something so i can do like below.
write-host "Results"
Write-Output $computerArray - display my first array here
write-host "Failed: computerlist" -foregroundcolor red
Write-Output $computerArray2 - display $error computers here. $error should just include computers who did not answer to ping and other stuff from my invoke-command computerlist.txt
The only true answer to why i need this separately is that sometimes i want my array in a CSV file. And sometimes i just want to copy info directly from Powershell window. And then its more practical to have failed computers separated and not in the same array output.
This function (as mentioned in comments) doesn't leverage the CIM cmdlets parallel capabilities, would recommend some tweaks to it but to answer the actual question, how can you "split" the output between success and fail:
The function as-is, doesn't require any modification to achieve this, it's try and catch blocks are outputting objects with the same properties and luckily one of those properties is Error and it's value is a boolean so you can simply first query all the computers and then split the result using .Where with Split mode.
The code would be like this:
$computers = 'computer1', 'computer2', ....
$computerArray = foreach($computer in $computers) {
Get-ComputerInformation -ComputerName $computer
}
# now we can split between FAIL and SUCCESS
$fail, $success = $computerArray.Where({ $_.Error }, 'Split')
$success | Export-Csv path\to\success.csv -NoTypeInformation
$fail | Export-Csv path\to\fail.csv -NoTypeInformation
I have a CSV file and in that file are 2 columns (this is just for testing purposes before using actual files), I need to get all the data for the specific pets so Dog and Cat in this example.
I have put the animals I want the data for in an array but for some reason the statement is not working it just returns an empty file, when I use a string (so just "dog") in the place of the array then I get the data back fine. Is there anything i'm doing wrong
$Pets = "Dog", "Cat"
import-csv -Path "C:\Users\User\deletingRows.csv" | where Animal -Contains $Pets | export-csv -Path "C:\Users\User\Result.csv" -NoTypeInformation
I believe you're misunderstanding what -Contains is supposed to do. Since you're trying to match a field against more than one value (within $Pets), you're better of using the -In switch. See the working example below.
$Pets = "Dog", "Cat"
Import-Csv -Path "C:\Users\User\deletingRows.csv" | where "Animal" -In $Pets | Export-Csv -Path "C:\Users\User\Result.csv" -NoTypeInformation
Working on a project and I have a need to replace a 'path prefix' with a different prefix. Automating the copying of files and then I will do using those files locally. Rather than making new variables I figured I would re-purpose old ones I would not need after the copy is complete. Ran into an issue with doing a replace when looping through the Array. I was able to find a solution for this particular scenario but would like to understand why my loops were not working
No errors are shown to give me an indication why it is not working.
Any help on understanding why the replace isn't working when looping would be helpful
Sample code of how I am building paths
[string]$Root_Path = "\\Main_Blah_Path\"
[string]$Software = $Root_Path + "Software\"
[string]$Adobe_Reader = $Software + "Adobe_Reader\"
[string]$Firefox = $Software + "Firefox\"
[string]$Google_Chrome = $Software + "Google_Chrome\"
[System.Collections.ArrayList]$List_Of_Software = #(
$Adobe_Reader
$Firefox
$Google_Chrome
)
Example of the ways I have done the replacement. These work and will write the desired output to the console
foreach ($Path in $List_Of_Software) {
$Path -replace '\\\\Main_Blah_Path\\','C:\Folder\'
}
$List_Of_Software | ForEach-Object {$_ -replace '\\\\Main_Blah_Path\\','C:\Folder\'}
Example of failures I am having. I cannot replace and save the data into itself to do a replacement. I couldn't get .replace to work at all
foreach ($Path in $List_Of_Software) {
$Path = $Path -replace '\\\\Main_Blah_Path\\','C:\Folder\'
}
$List_Of_Software | ForEach-Object {$_ = $_ -replace '\\\\Main_Blah_Path\\','C:\Folder\'}
foreach ($Path in $List_Of_Software) {
$Path.Replace('\\\\Main_Blah_Path\\','C:\Folder\')
}
Solution I am using for my current scenario but I can foresee a few things in my future where this method may not be a viable option
$List_Of_Software = $List_Of_Software -replace '\\\\Main_Blah_Path\\','C:\Folder\'
You're almost there, you just need to assign the results of the replacement back to the variable when you're looping the array. Try:
$List_of_software = $List_Of_Software |
ForEach-Object {$_ -replace '\\\\Main_Blah_Path\\','C:\Folder\'}
Would like to retrive innerText of a P html element for all the URLS i got listed in a text file. I'm rather newbie for this, but thought i can solve it. Atm. i've failed, as i can't handle how i shall pass each array items for the loop correctly:
$theURLS = Import-CSV linkek_alatt.txt
$item = New-Object System.Collections.ArrayList
for ($i=0; $i -le $theURLS.length;$i++)
{
foreach($item in $theURLS)
{
$Site = Invoke-WebRequest -URI $item
$Igotit = $Site.AllElements | Where-Object {$_.tagName -eq "P"} |
Select -First 1 -Skip 3 -ExpandProperty innerText
$Igotit
}
}
> FilteredContent.txt
The Filtered file shall contain the informations.
For now, i receive a "Invoke-WebRequest : Cannot bind parameter 'Uri'. Cannot convert the "#{" error and i see repeated first URL and a random - the one for next step - one in the error message. Any ideas welcome.
Best regards,
Geza
Per the comments, the issue occurs because you are using Import-CSV here:
$theURLS = Import-CSV linkek_alatt.txt
This attempts to create a PowerShell object by using the first line of text in the file as headers.
If your .txt file is not a .csv file and you want to return an array of strings, instead use Get-Content:
$theURLS = Get-Content linkek_alatt.txt
If your file is a CSV file, then you'll need to reference the property name that matches the header of the URLs when using it in Invoke-WebRequest. E.g if it had a header of "URL":
Invoke-WebRequest -URI $item.URL
But I suspect this is not the case for you.
I have a single dimensional array that I get from either a get-content command or from multi-line text box input. I want to assign a property to the entries in this array, then add more properties to use later in my script.
Something like:
$items = new-object psobject
$items | add-member -membertype NoteProperty –name Name –value NotSet
$items | add-member -membertype NoteProperty –name Percent –value NotSet
$names = #($textboxInputText.Lines)
$names | % { $items | Add-Member noteproperty $_.Name $temp.($_.Name) }
foreach ($item in $items)
{
$percent = {script block}
$item.percent = $percent
}
I know this is broken code, but I wanted to give an example of where I was headed. I've searched far and wide but haven't been able to find exactly what I was looking for.
EDIT:
Code Goal: Get input from a text box or text file (single line entries). Have those entries be assigned to the "name" property, then add a second property to the array (Percent) that will need to be filled in with another block of code.
EDIT 2:
Collection is being used in the following code:
foreach ($item in $collection) {
$psConsoleFile = "PATH TO FILE.pc1"
$variable1 = "something"
$variable2 = "something else"
$command = ".`"Command1 $item.name | Command2 -Switch $variable1 -Switch2 $variable2`""
$OutputScriptBlock = "powershell.exe -PSConsoleFile $psConsoleFile -command $command"
}
The output of this is as follows:
powershell.exe -PSConsoleFile "PATH TO FILE.psc1" -command ."Command1 #{Name=name1; Percentage=}.name | Command2 -Switch1 something"
Why is the code outputting the full row instead of the name?
Also, I'm using PS 4.0 for all implementations of this script.
Ok, I see the problem here. So you have an array of Strings that you got either from a multi-line text box form object, or from a text document with the Get-Content command, but what you really want is an array of PSObjects.
A string object can not have additional properties added to it like you want (well, not conventionally, let's just not go there because you won't be happy with where things end up, trust me on this one). Instead let's take that array of strings, and for each string create a PSObject for it like you want. You will want a ForEach-Object loop for this to be simple. Either way you will want to pipe your input (either the textbox or the get-content command) to a ForEach loop, and you can assign the whole thing to a variable that will collect all of the objects to be worked with later (to update the Percent property). Something like this should accomplish what you want:
[Array]$Collection = $textboxInputText.Lines | ForEach{
New-Object PSObject -Property #{
'Name' = $_
'Percentage' = $null
}
}
I specified $Collection as the type [Array] so that if you wanted to index into it later there wouldn't be any issues should your input only be a single item. Then if you want to update the percentages you can do that by running $Collection through a ForEach loop (either inline or not)
$Collection | ForEach{ $_.Percentage = {Script Block} }
or
ForEach($Item in $Collection){
$Item.Percentage = {Script Block}
}
Now, things to note here... You are not going to be able to just assign $Collection back to your textbox. You could probably assign $Collection.Name, but that may require a newer version of PS since I don't know how backwards compatible that is. If you use a Get-Content command instead of referencing the textbox, simply change $textboxInputText.Lines | ForEach{ to Get-Content "C:\Path\To\File.txt" | ForEach{ and you should be all set.
Edit: Ok, the problem you have now isn't with the object but with how you're trying to expand a property of it within a double quotes. To access the name you would have to create a sub expression within the double quotes by wrapping $Item.Name within $(). So that line for you would look like:
$command = ".`"Command1 $($item.name) | Command2 -Switch $variable1 -Switch2 $variable2`""