Link to home
Start Free TrialLog in
Avatar of bndit
bndit

asked on

Powershell regex

Hello,

I'm trying to understand regular expressions in powershell, but seem to be having a hard time. I have a CSV file and I need to extract a value (IP address) from one of the columns. The column looks like this:

kdajfakldjfa.en.jlkjdaflsa.com.us.[192.168.4.0]dafldsj.com.us.ldaskjfkdsj
kdajfakldjfa.en.jlkjdaflsa.com.us.[192.168.5.0]dafldsj.com.us.ldaskjfkdsj
kdajfakldjfa.en.jlkjdaflsa.com.us.[192.168.6.0]dafldsj.com.us.ldaskjfkdsj
kdajfakldjfa.en.jlkjdaflsa.com.us.[192.168.7.0]dafldsj.com.us.ldaskjfkdsj

Obviously IP address are gonna differ so my regex filter would say find the first "[" and extract everything inside until you find the closing bracket "]"

I've tried doing this, but not getting me anywhere

$ips = import-csv c:\myfile.csv
foreach ($line in $lines){
     $line = regex::($line,"^\]")
}

can't seem to figure out how to say "extract everything until you find the next bracket"
Avatar of cantoris
cantoris
Flag of United Kingdom of Great Britain and Northern Ireland image

How's about:

   $line -match "\[(.+)\]"
   $ip = $matches[0]
Sorry, make that  $matches[1]
ASKER CERTIFIED SOLUTION
Avatar of cantoris
cantoris
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Qlemo
Explanation: -match works in the way that it applies the right-hand RegExp against the left-hand value. Anything grouped (in parens) in the RegExp will result into an own group in the $matches array, with $matches[0] being the whole string.
The RegExp used will catch all contents between the first and the last (!) square bracket - default mode for RegExp is "lazy", which means the widest fit. You will need to make sure you do not have more than one square bracket'd value per line in your CSV file, but I reckon that is ok.
Avatar of bndit
bndit

ASKER

Ok, so that works...now I'm trying to send the output to a text file but it's lumping everything together as opposed to placing each IP address on its own line such as:

192.168.0.2
192.168.0.3

my current output:

192.168.0.2192.168.0.3
$lines = Import-Csv C:\file.csv
$ips = @()
foreach($line in $lines){
	
	
	 If ($line -match "\[(.+)\]") {$ips += $matches[1]}
}
$ips | Set-Content c:\cleanips.txt

Open in new window

Avatar of bndit

ASKER

Nevermind...it was a simple fix

If ($line -match "\[(.+)\]") {$ips += $matches[1] + "`\n"}
Avatar of bndit

ASKER

Spoke too soon.....it's "`n" instead of "`\n" and it only works when I run the script from within the PowerGui editor and send the output to the screen...but not when the output is sent to a text file...any ideas why?
Avatar of bndit

ASKER

Strange....added "`r`n" and it worked when I sent the output to a text file.....why would `n not work?
Windows uses a line feed and carriage return at the end of each line, whereas linux systems just use a carriage return - sometimes there is compatibility between the 2 methods, but it often causes trouble.
Strange, because you should not need to insert newline and/or carriage return when outputting array content. It works for me in the plain PowerShell prompt:
$ip = @()
$ip += "192.168.1.1"
$ip += "192.168.1.2"
$ip | set-content c:\cleanips.txt

Open in new window

But the "proper" way to process and output is
get-content C:\file.csv | % {if ($_ -match "\[(.+)\]") {$matches[1]} } | Set-Content c:\cleanips.txt

Open in new window

In particular I cannot see anything CSV like in the snippet you provided, and so there is no need to use the import-csv; get-content will do better here, as it just reads the complete line as a single string.
My help was not worth some points?