Reputation: 57
Trying to find the numbers in my file divisible by 3. How can I make my for each loop read each number individually?
this is my file:
6 9 7
-----
5 2 9
3 4 4
1 6 9
This is my code so far:
function number{
param($b)
# Loop through all lines of input
foreach($a in $b){
if ($line = % 3)
{
Write-Output "divisible by 3"
}
else {
Write-Output "number not divisible by 3"
}
}
}
#Variables
#Get input from csv file
$a = Import-Csv "document 2.Dat"
Upvotes: 0
Views: 124
Reputation: 28963
How have you got this far in, without realising that none of that even does anything at all? Whatever development approach you're using, you need to rethink it.
Hints that something is wrong:
How is it printing more dashes than there even are in the file? What is it actually printing? Use useful debugging/testing tool, wrap each thing in dashes so you can see where they start and end:
Oh that's broken.
Inside function number {
put write-host 'hello?'
and see that it's never printing anything.
Try calling the function by hand to see what it does:
Oh I have no idea what number is not divisible by 3, I'd better fix that so I can see what's going on.
And if you have an eye looking for details
where does $line
get assigned? What is =
doing in an if
test? What is % 3
doing with nothing to the left of the %? Why am I using variable names like $a
and $b
which don't help me follow what's happening at all?
and, of course, "*why am I not write-host "..."
all the way through, and/or stepping through this code in the debugger to see what's happening?
That's my file alright. And the limits of the output are ... lines. Cool.
function number
I should give it a better name but.Sigh. alright, alright.
No output, even from a simple 'hi'? Ah, call the function.
Great.
Pass a parameter to it and print it...
No output.
Enough screenshots.
Pass a parameter when calling the function. Get-NumbersWhichDivideEvenlyByThree $FileContent
Iterate over the lines and print them inside the function.
Google "powershell get numbers from string" and stuff
Iteratively develop your code, going from working block to working block. Never end up in a position where you have a dozen lines that all don't work in half a dozen different ways all at once, and nowhere to go from there.
Bit you actually asked
Get numbers out of a string.
Use regex. This is exactly why they exist. But to try and keep it simple - in a way that's actually more complicated but tough - break the lines apart on spaces, and pick out the pieces which are numbers and throw the rest away.
To get this with a reasonably nice answer, you almost need to just magically know about -split
, perhaps by stumbling on one of @mklement0's answers here about unary split or split has an unary form or the unary form of the -split operator is key here , or, I guess, have read help about_Split
in careful detail.
-split '6 9 7' # this splits the line into parts on *runs* of whitespace
6
9
7 # look like numbers, but are strings really
So you get some text pieces, including the line of -----
in the file, that will be among them. And you need to test which are numbers and keep them, and which are dashes (letters, punctuation, etc) and throw those away.
$thing -as [int] # will try to cast $thing as a (whole) number, and silently fail (no exception) if it cannot.
# Split the line into pieces. Try to convert each piece to a number.
# Filter out the ones which weren't numbers and failed to convert.
$pieces = -split $line
$pieces = $pieces | ForEach-Object { $_ -as [int] }
$numbers = $pieces | Where-Object { $_ -ne $null }
Then you can do the % 3
test. And have code like:
function Get-NumbersWhichDivideEvenlyByThree {
param($lines)
foreach ($line in $lines)
{
$pieces = -split $line
$pieces = $pieces | ForEach-Object { $_ -as [int] }
$numbers = $pieces | Where-Object { $_ -ne $null }
foreach ($number in $numbers)
{
if (0 -eq $number % 3)
{
Write-Output "$number divisible by 3"
}
else
{
Write-Output "$number not divisible by 3"
}
}
}
}
$FileContent = Get-Content 'D:\document 2.dat'
Get-NumbersWhichDivideEvenlyByThree $FileContent
and output like:
(-split(gc D:\test.txt -Raw)-match'\d+')|%{"$_$(('',' not')[$_%3]) divisible by 3"}
Upvotes: 4