Pante
Pante

Reputation: 11

Math from a file.txt

    $space =("`r`n")
    $data = @(Get-Content C:\Users\user1\Desktop\ma.txt)
    $Array = ($Data.Split($space)).Split($space)
    $pos1 = $Array[0][0]+$Array[0][1]
    $pos2 = $Array[1][0]+$Array[1][1]
    $pos3 = $Array[2][0]+$Array[2][1]
    #$pos1
    #$pos2 
    #$pos3
    $zahl1 = $Array[0][5]+$Array[0][7]+$Array[0][9]
    $zahl1

PowerShell 7.2

txt1.txt has the text:

x1 = 2 + 3

x2 = 8 / 4

x3 = 1 - 4

i want the results (from x1,x2,x3) to be saved at txt2.txt with a command in Terminal. I tried whith Arrays, but i only get :2+3 instead of 5

Any thoughts?

Upvotes: 1

Views: 71

Answers (2)

zett42
zett42

Reputation: 27756

This is an attempt of a more secure version, that matches only mathematical expressions, so users cannot run arbitrary code through Invoke-Expression:

Get-Content text1.txt | 
    Select-String '^\s*(\S+)\s*=([\d\.+\-*/%\(\)\s]+)$' | 
    ForEach-Object {
        $var        = $_.Matches.Groups[ 1 ].Value
        $expression = $_.Matches.Groups[ 2 ].Value
        $result     = Invoke-Expression $expression
        "{0} = {1}" -f $var, $result
    } | 
    Set-Content text2.txt

The Select-String cmdlet uses a regular expression to match only lines that are considered "safe". Within the RegEx there are two groups defined to split the line into variable (1) and calculation (2) sub strings. These are then extracted via $_.Matches.Groups.

RegEx breakdown:

Pattern Description
^ line start
\s* zero or more whitespace characters
( start 1st capturing group
\S+ one or more non-whitespace characters
) end 1st capturing group
\s* zero or more whitespace characters
= literal "="
( start 2nd capturing group
[ start list of allowed characters
  \d\.+\-*/%\(\)\s digits, dot, math ops, parentheses, whitespace
] end the list of allowed characters
+ one or more chars (from the list of allowed characters)
) end 2nd capturing group
$ line end

Upvotes: 1

Theo
Theo

Reputation: 61028

You could use Invoke-Expression for this, but read the warning first

Get-Content -Path text1.txt | Where-Object {$_ -match '\S'} | ForEach-Object {
    $var,$calculation = ($_ -split '=').Trim()
    '{0} --> {1}' -f $var, (Invoke-Expression -Command $calculation)
} | Set-Content -Path text2.txt

Upvotes: 4

Related Questions