KQL Syntax using a variable - Exchange 2013 - exchange-server

This works as expected:
Search-Mailbox jdoe -SearchQuery 'sent:"today" AND subject:"1234"' -EstimateResultOnly
It returns 1 result as it should.
Trying to replace 1234 with a variable but in vain. I figure it's an issue with my syntax but I've tried just about every combination of quotes and doublequotes and still it doesnt return anything.
$subject = "1234"
Search-Mailbox jdoe -SearchQuery {'sent:"today" AND subject:"'$subject'"'} -EstimateResultOnly
How can I replace "1234" with a variable?

Because {'sent:"today" AND subject:"'$subject'"'} is a scriptblock http://blogs.technet.com/b/heyscriptingguy/archive/2013/05/22/variable-substitution-in-a-powershell-script-block.aspx your varible won't expand. So you just need to construct the script block like
$Varible = "1234"
$Search = [scriptblock]::create("'sent:`"today`" AND subject:$Varible'")
Search-Mailbox jdoe -SearchQuery $Search -EstimateResultOnly
Cheers
Glen

Related

How to give a text file into a shell function?

Hi I'm trying to make a function which should get a text file and then do some things on it and then echo. But when I try to execute it, it says syntax error near unexpected token `"$cat"'
#!/bin/usr/bash
cat=$(< cat_dialogue.txt)
function test_cat (){
echo $1
}
test_cat($cat)
desired output:
>meow meow
Your program may look like the following. Note all differences. Check your scripts with shellcheck.
#!/usr/bin/env bash
cat=$(< cat_dialogue.txt)
test_cat() {
echo "$1"
}
test_cat "$cat"
Here is an example BASH function that strips a branchname:
#create function
function strip () {
#create local variable that takes input and fills $TEXT
local TEXT=$1
#stips the branch number from the branchname
echo $TEXT | sed 's/-[0-9]*//2'
}
strip "testbranch-12345-28796"
hope it helps :) also check the BASH documentation as mentioned by #joshmeranda

Export text ouput into csv format ready for insert into databases using Powershell

I wish to pipe aws cli output which appears on my screen as text output from a powershell session into a text file in csv format.
I have researched the Export-CSV cmdlet from articles such as the below:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-csv?view=powershell-7.1
I cannot see how to use this to help me with my goal. From my testing, it only seems to work with specific windows programs, not general text output.
An article on this site shows how you can achieve my goal with unix commands, by replacing spaces with commas.
Output AWS CLI command with filters to CSV without jq
The answer with unix is to use sed at the end of the command like so:
aws rds describe-db-instance-automated-backups --query 'DBInstanceAutomatedBackups[*].{ARN:DBInstanceArn,EarliestTime:RestoreWindow.EarliestTime,LatestTime:RestoreWindow.LatestTime}' --output text | sed -E 's/\s+/,/g'
Export-csv` appears to not be able to do this.
Does anyone know how I might replicate what sed is doing here with powershell?
Here is an example of the output that I would like in csv format:
arn:aws:rds:ap-southwest-2:9711387875370:db:catflow--prod 2019-03-03T09:54:29.402Z 2019-03-05T01:25:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:xyz-prod-rds-golf 2019-03-01T09:04:31.477Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-stardb 2019-02-01T09:07:30.648Z 2019-03-05T01:27
:20Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-domaindb 2019-02-02T09:04:30.771Z 2019-03-05T01:28
:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-ctz-prod-rds-datavault 2019-02-26T14:14:30.254Z 2019-03-05T01:29
:13Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-gcp-prod-rds-datavault 2019-02-01T14:05:40.456Z 2019-03-05T01:31
:05Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-conformed-datavault-prod 2019-02-02T14:06:26.050Z 2019-03-
05T01:27:02Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-dqm-datavault-prod 2019-02-01T14:12:05.286Z 2019-03-05T01:26
:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-prod-dgc-cde-lineage 2019-03-02T09:54:29.053Z 2019-03-05T01:29
:11Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-rec-prod 2019-02-02T22:09:00.673Z 2019-03-05T01:29:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-serve-prod 2019-03-02T09:54:20.729Z 2019-03-05T01:30:21Z
It's possible that you are working with a tab delimited text file, with no headers.
The tab separator can look like multiple spaces when it is displayed on your screen.
If this is the case, If so, you can actually read this file with import-csv, but you have to use the -header parameter to supply your own field names, and the -delimiter character to use tab as the delimiter. The tab character has to be specified using the backtick escape mechanism.
For details, see the accepted answer to this question.
If you have control over your data feed, there is an alternative. The aws cli interface has an option to format the output in JSON format. That format will be much easier to import into Powershell in a form you can use.
Edit:
The following script uses the mockup provided by Theo, except that the multiple spaces have been replaced by a tab character. It uses ConvertFrom-Csv rather than Import-Csv, but it's the same idea:
$awsReturn = #"
arn:aws:rds:ap-southwest-2:9711387875370:db:catflow--prod 2019-03-03T09:54:29.402Z 2019-03-05T01:25:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:xyz-prod-rds-golf 2019-03-01T09:04:31.477Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-stardb 2019-02-01T09:07:30.648Z 2019-03-05T01:27:20Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-domaindb 2019-02-02T09:04:30.771Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-ctz-prod-rds-datavault 2019-02-26T14:14:30.254Z 2019-03-05T01:29:13Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-gcp-prod-rds-datavault 2019-02-01T14:05:40.456Z 2019-03-05T01:31:05Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-conformed-datavault-prod 2019-02-02T14:06:26.050Z 2019-03-05T01:27:02Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-dqm-datavault-prod 2019-02-01T14:12:05.286Z 2019-03-05T01:26:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-prod-dgc-cde-lineage 2019-03-02T09:54:29.053Z 2019-03-05T01:29:11Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-rec-prod 2019-02-02T22:09:00.673Z 2019-03-05T01:29:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-serve-prod 2019-03-02T09:54:20.729Z 2019-03-05T01:30:21Z
"#
$myarray = $awsreturn | ConvertFrom-Csv -header "Prod","DateStart","DateEnd" -delimiter "`t"
$myarray | Format-Table
$myarray | gm
When I ran it in my environment, it produced the following:
Prod DateStart DateEnd
---- --------- -------
arn:aws:rds:ap-southwest-2:9711387875370:db:catflow--prod 2019-03-03T09:54:29.402Z 2019-03-05T01:25:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:xyz-prod-rds-golf 2019-03-01T09:04:31.477Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-stardb 2019-02-01T09:07:30.648Z 2019-03-05T01:27:20Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-domaindb 2019-02-02T09:04:30.771Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-ctz-prod-rds-datavault 2019-02-26T14:14:30.254Z 2019-03-05T01:29:13Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-gcp-prod-rds-datavault 2019-02-01T14:05:40.456Z 2019-03-05T01:31:05Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-conformed-datavault-prod 2019-02-02T14:06:26.050Z 2019-03-05T01:27:02Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-dqm-datavault-prod 2019-02-01T14:12:05.286Z 2019-03-05T01:26:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-prod-dgc-cde-lineage 2019-03-02T09:54:29.053Z 2019-03-05T01:29:11Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-rec-prod 2019-02-02T22:09:00.673Z 2019-03-05T01:29:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-serve-prod 2019-03-02T09:54:20.729Z 2019-03-05T01:30:21Z
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
DateEnd NoteProperty string DateEnd=2019-03-05T01:25:53Z
DateStart NoteProperty string DateStart=2019-03-03T09:54:29.402Z
Prod NoteProperty string Prod=arn:aws:rds:ap-southwest-2:9711387875370:db:catflow--prod
Lets assume the data returned looks like this mockup (in the question it is strangely formatted):
$awsReturn = #"
arn:aws:rds:ap-southwest-2:9711387875370:db:catflow--prod 2019-03-03T09:54:29.402Z 2019-03-05T01:25:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:xyz-prod-rds-golf 2019-03-01T09:04:31.477Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-stardb 2019-02-01T09:07:30.648Z 2019-03-05T01:27:20Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-domaindb 2019-02-02T09:04:30.771Z 2019-03-05T01:28:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-ctz-prod-rds-datavault 2019-02-26T14:14:30.254Z 2019-03-05T01:29:13Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-gcp-prod-rds-datavault 2019-02-01T14:05:40.456Z 2019-03-05T01:31:05Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-conformed-datavault-prod 2019-02-02T14:06:26.050Z 2019-03-05T01:27:02Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-dqm-datavault-prod 2019-02-01T14:12:05.286Z 2019-03-05T01:26:53Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-prod-dgc-cde-lineage 2019-03-02T09:54:29.053Z 2019-03-05T01:29:11Z
arn:aws:rds:ap-southwest-2:9711387875370:db:prod-rec-prod 2019-02-02T22:09:00.673Z 2019-03-05T01:29:40Z
arn:aws:rds:ap-southwest-2:9711387875370:db:-serve-prod 2019-03-02T09:54:20.729Z 2019-03-05T01:30:21Z
"#
Then, you can do this:
# Since I don't know if that is one single string or a string array:
if ($awsReturn -isnot [array]) { $awsReturn = $awsReturn -split '\r?\n' }
# write it to csv file
$awsReturn -replace '\s+', ',' | Set-Content -Path 'WhereEver.csv' -PassThru # PassThru also displays on screen
to get a file that can serve as CSV (although it has no headers or quoted fields)
If you want to use Export-CSV to get a csv file with headers and quoted fields, you need to split the lines and output objects.
Something like this:
# Since I don't know if that is one single string or a string array:
if ($awsReturn -isnot [array]) { $awsReturn = $awsReturn -split '\r?\n' }
# write it to csv file (without headers or quotes values)
$awsReturn | ForEach-Object {
$data = $_ -split '\s+' # in this case we know we have 3 fields
[PsCustomObject]#{
Prod = $data[0]
DateStart = $data[1]
DateEnd = $data[2]
}
} | Export-Csv -Path 'WhereEver.csv' -NoTypeInformation
The WhereEver.csv file will then look like this:
"Prod","DateStart","DateEnd"
"arn:aws:rds:ap-southwest-2:9711387875370:db:catflow--prod","2019-03-03T09:54:29.402Z","2019-03-05T01:25:53Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:xyz-prod-rds-golf","2019-03-01T09:04:31.477Z","2019-03-05T01:28:40Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-stardb","2019-02-01T09:07:30.648Z","2019-03-05T01:27:20Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:-asm-prod-rds-domaindb","2019-02-02T09:04:30.771Z","2019-03-05T01:28:40Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:-ctz-prod-rds-datavault","2019-02-26T14:14:30.254Z","2019-03-05T01:29:13Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:-gcp-prod-rds-datavault","2019-02-01T14:05:40.456Z","2019-03-05T01:31:05Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:prod-conformed-datavault-prod","2019-02-02T14:06:26.050Z","2019-03-05T01:27:02Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:prod-dqm-datavault-prod","2019-02-01T14:12:05.286Z","2019-03-05T01:26:53Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:prod-prod-dgc-cde-lineage","2019-03-02T09:54:29.053Z","2019-03-05T01:29:11Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:prod-rec-prod","2019-02-02T22:09:00.673Z","2019-03-05T01:29:40Z"
"arn:aws:rds:ap-southwest-2:9711387875370:db:-serve-prod","2019-03-02T09:54:20.729Z","2019-03-05T01:30:21Z"

Execute cmdlet through variable?

I want to use an if \ else statement to determine which cmdlet to run while keeping the same params for both commands:
For example I have this call:
New-AzureRmResourceGroupDeployment `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
But I want to use a variable to determine the verb:
$myVerb = if ($booleanTest) {"Test"} else {"New"}
[$myVerb]-AzureRmResourceGroupDeployment `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
OR something like this:
$command = if ($booleanTest) {"Test-AzureRmResourceGroupDeployment"} else {"New-AzureRmResourceGroupDeployment"}
$command `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
I tried the $command version but it failed with this:
At
C:\Users\Administrator\Dropbox\projects\deloitte\Suncore\Dev\scripts\az-d
eploy.ps1:36 char:13
+ -ResourceGroupName $ResourceGroup
+ ~~~~~~~~~~~~~~~~~~ Unexpected token '-ResourceGroupName' in expression or statement. At
C:\Users\Administrator\Dropbox\projects\deloitte\Suncore\Dev\scripts\az-d
eploy.ps1:36 char:32
+ -ResourceGroupName $ResourceGroup
+ ~~~~~~~~~~~~~~
To do exactly what you are describing you'd need to wrap the whole command as a string and then call it with Invoke-Expression. For Example:
$MyCommand = "$myVerb-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroup -TemplateFile $TemplateUri"
Invoke-Expression $MyCommand
But I think this isn't a very clear way to write a script. A better option would be to use Splatting, which is where you create a hashtable of the parameters that you can then send the cmdlet via a special # character with the variable name. For example:
$AzureParams = #{
ResourceGroupName = $ResourceGroup
TemplateFile = $TemplateUri
TemplateParameterFile = $TemplateParamFile
}
If ($booleanTest) {
Test-AzureRmResourceGroupDeployment #AzureParams
} Else {
New-AzureRmResourceGroupDeployment #AzurParams
}
This also has the benefit of avoiding using the backtick character, which is generally encouraged as it's hard to spot and easy to break.
I don't recommend using this over the other answer but to directly answer your question, add the invocation operator &
$command = if ($booleanTest) {
"Test-AzureRmResourceGroupDeployment"
} else {
"New-AzureRmResourceGroupDeployment"
}
& $command `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
To complement the existing helpful answers:
Invoke-Expression should always be the last resort and is not needed here. With Invoke-Expression, it is tricky to get the quoting right, and its use can be a security risk (execution of arbitrary commands passed as a string, analogous to eval in POSIX-like shells).
Splatting (Get-Help about_Splatting) is always worth considering:
it is a more robust alternative to multi-line parameter-passing with line continuations, as Mark's answer explains.
it allows incremental, conditional construction of the set of parameter values as well as their use in multiple invocations.
In the case at hand, however, since only the command name is variable, Patrick's answer based on &, the call operator is simplest (see Get-Help about_Operators).
Generally, you need & whenever the command name is not an unquoted literal (e.g., notepad foo.txt works, but 'notepad' foo.txt doesn't).
To put it differently: you need &, if your command name is:
in quotes (whether '...' or "..."); e.g., 'notepad'
or is a variable reference; e.g., $cmdName
or is the result of an expression (e.g., ('get' + '-item')
& is needed in theses case in order to tell PowerShell that your intent is to invoke a command as opposed to evaluating an expression; without &, such tokens would be interpreted as starting an expression; see Get-Help about_Parsing to learn about PowerShell's two fundamental parsing modes, argument mode and expression mode.
While it may not be the most readable solution, you can therefore even combine an expandable string with an embedded subexpression ($(...) - again, see Get-Help about_Operators) to get away without the need for an aux. variable:
& "$( if ($booleanTest) {'Test'} else {'New'} )-AzureRmResourceGroupDeployment" `
-ResourceGroupName $ResourceGroup `
-TemplateFile $TemplateUri `
-TemplateParameterFile $TemplateParamFile
Using Splatting as suggested by Mathias R. Jessen:
Function Do-AzureRmResourceGroupDeployment ([ValidateSet("Test", "New")]$Verb, $ResourceGroupName, $TemplateFile, $TemplateParameterFile) {
$PSBoundParameters.Remove("Verb")
& "$Verb-AzureRmResourceGroupDeployment" #PSBoundParameters
}

How to assign variables to a Powershell script from a file?

I am trying to deploy 20 vms in vcenter using vsphere powerCLI, instead of prompting for vmname/hostname again and again or passing params for 20 times I am looking for passing the 20 vm names from a file.
You can do this in a quick one-liner, create a csv file with the headings and values you want to use like so:
VMName,Hostname
VM001,Server01
VM002,Server02
VM003,Server03
Then use Import-CSV and Foreach to loop through the file and run your command (New-VM used as an example) with the fields from each row.
Import-Csv C:\folder\file.csv | Foreach { New-VM -VMName $_.VMName -Hostname $_.Hostname }
$1 = Get-content PATH
$1[ROWNUMBER]
That would be how to import the file, and then select a row number in it.
Seeing you wanted to use each line you could do something like this:
$1 = Get-content PATH
Foreach($Row in $1){
New-VM $row
}

IPV6 address shortening in shell and powershell

I have to make a script in shell and PowerShell that shortens ipv6 addresses as much as possible.
Like:
Input: 2001:0db8:03cd:0000:0000:ef45:0006:0123
Output: 2001:db8:3cd:::ef45:6:123
And the script should give a description of itself if -help parameter used but i dont know how to do that in PowerShell.
This is my code in PowerShell, it shortens the addresses correctly:
param([parameter(Mandatory=$true)]$file)
if (test-path $file){
foreach ($ip in Get-Content $file){
$ip=$ip.Replace("0000","")
Write-Host $ip
}
}
I have no idea how to do the shortening in shell, I tried like this but didn't work:
#!/bin/sh
if [ $1 = "-help" ]
then
echo description
else file = $1
fi
for ip in `cat ipv6.txt`
do
$ip=$line
$replace=""
$echo ${var//0000/$replace}
done
This is the txt file with the addresses:
http://uptobox.com/6woujdvdfkmh
The beauty of PowerShell is that you have access to a rich library that has methods for doing this for you. Try this:
<#
.SYNOPSIS
Converts long form IP address into its short form
.DESCRIPTION
Converts long form IP address into its short form
.PARAMETER IPAddress
The IP address to convert.
.EXAMPLE
PS C:\> ConvertTo-IPAddressCompressedForm 2001:0db8:03cd:0000:0000:ef45:0006:0123
#>
function ConvertTo-IPAddressCompressedForm($IPAddress) {
[System.Net.IPAddress]::Parse($IPAddress).IPAddressToString
}
C:\> ConvertTo-IPAddressCompressedForm 2001:0db8:03cd:0000:0000:ef45:0006:0123
2001:db8:3cd::ef45:6:123
Note that to get usage in PowerShell based on the doc comments use:
ConvertTo-IPAddressCompressedForm -?
We might be going to the same school. This is what I was told to do and it works perfectly:
cat filename | sed -e 's/:0*/:/g' filename
$longIPAddress = '2001:0db8:03cd:0000:0000:ef45:0006:0123'
$shortIPAddress = ([IPAddress]$longIPAddress).IPAddressToString
$shortIPAddress
2001:db8:3cd::ef45:6:123

Resources