Famil Semedli
Famil Semedli

Reputation: 9

I need to convert this code to PowerShell

I wrote this Linux Shell script in Linux now i want to write it in PowerShell

manu="$1"

sort -t';' -nrk3 auto1.dat | grep "$manu" | head -n1 | cut -d';' -f2

I did sort like this:

$car = Import-Csv -Header "Manufacturer" , "Model" , "Price" -delimiter ';' auto.dat
$car | % { $_.Price = [int]$_.Price }
$car | Sort-Object Price -Descending

but i can find information about how to do grep and head or cut i tried few things and it didn't work. So basically what I want is

.\car.ps1 Tesla

this code should give me expensive model of Tesla

and auto.dat file contains cars and models and prices:

Lamborghini;Aventador;700000
Lamborghini;Urus;200000
Tesla;ModelS;180000
Tesla;ModelX;140000
Ford;Mustang;300000
Ford;Focus;20000
Audi;A8;100000
Audi;R8;500000

Upvotes: 0

Views: 93

Answers (2)

Bacon Bits
Bacon Bits

Reputation: 32170

You want to look at Get-Help about_Functions_Advanced_Parameters and Get-Help about_Functions_Advanced. You can make a script work like a function by removing the function statement and outer braces from it.

So, you can take this function:

function car {
[CmdletBinding()]
Param (
    [Parameter(Mandatory=$true,Position=1)]
    [String]
    $Manufacturer
)

Import-Csv -Path auto.dat -Header "Manufacturer","Model","Price" -Delimiter ';' |
    Where-Object { $_.Manufacturer -match $Manufacturer } |
    Sort-Object -Property @{e={[int]$_.Price}} -Descending |
    Select-Object -First 1
}

And save this as .\Car.ps1:

[CmdletBinding()]
Param (
    [Parameter(Mandatory=$true,Position=1)]
    [String]
    $Manufacturer
)

Import-Csv -Path auto.dat -Header "Manufacturer","Model","Price" -Delimiter ';' |
    Where-Object { $_.Manufacturer -match $Manufacturer } |
    Sort-Object -Property @{e={[int]$_.Price}} -Descending |
    Select-Object -First 1

Call it:

.\Car.ps1 -Manu Audi
.\Car.ps1 -M Tesla
.\Car.ps1 Ford

Upvotes: 3

briantist
briantist

Reputation: 47792

The major difference you need to be aware of between PowerShell and bash (Unix in general) when it comes to piping, is that in PowerShell you are generally dealing with real objects, not text streams.

So the beauty of what you have done so far, is that you don't need the head and cut commands at all.

The head command, which was (presumably?) skipping your header row, is already taken care of by specifying the headers to Import-Csv.

The result of Import-Csv is an array of objects (one for each row), and each column in the CSV is a single property of the row object, with the same name as the header.

If you want the name of the model in the first row, you use this:

$car[0].Model

Your last line sorts all the rows by price, but then it just sends that information out the pipeline.

So instead it seems what you want, is to use the parameter passed into the script (the manufacturer), to then find the most expensive model that manufacturer has.

There are lots of ways to do this, lots of ways to structure this, but I'll show you a very PowerShell way using the capabilities of the pipeline and the full objects.

Replacing your third line, I'd do something like this:

$car | 
    Where-Object { $_.Manufacturer -eq $args[0] } | 
    Sort-Object Price -Descending | 
    Select-Object -ExpandProperty Model -First 1

Note you can line break after a pipe, easier to read.

Here I'm going through the rows, filtering out the ones where the manufacturer matches, then sorting by price (descending), then taking the first 1 and keeping only the Model property.

I do recommend taking a proper named parameter, (as shown in Bacon Bits's answer) instead of using $args.

Upvotes: 1

Related Questions