Combining String and Variable causes leading extra Space [duplicate] - powershell

When I use Write-Host within a Foreach-Object, I get an unnecessary space in the output.
write-host "http://contoso.com/personal/"$_.ADUserName
Output:
http://contoso.com/personal/ john.doe
How can I remove the space before john? Trim does not work because there is no space in $_.ADUserName

This is happening because Write-Host is considering your constant string and your object to be two separate parameters -- you aren't actually joining the strings together the way you're calling it. Instead of calling it this way, actually concatenate the strings:
write-host "http://contoso.com/personal/$($_.ADUserName)"
or
write-host ("http://contoso.com/personal/" + $_.ADUserName)
or
write-host ("http://contoso.com/personal/{0}" -f $_.ADUserName)

Just do it without write-host:
"http://contoso.com/personal/{0}" -f $_.ADUserName

Related

Unnecessary space in output when using Write-Host

When I use Write-Host within a Foreach-Object, I get an unnecessary space in the output.
write-host "http://contoso.com/personal/"$_.ADUserName
Output:
http://contoso.com/personal/ john.doe
How can I remove the space before john? Trim does not work because there is no space in $_.ADUserName
This is happening because Write-Host is considering your constant string and your object to be two separate parameters -- you aren't actually joining the strings together the way you're calling it. Instead of calling it this way, actually concatenate the strings:
write-host "http://contoso.com/personal/$($_.ADUserName)"
or
write-host ("http://contoso.com/personal/" + $_.ADUserName)
or
write-host ("http://contoso.com/personal/{0}" -f $_.ADUserName)
Just do it without write-host:
"http://contoso.com/personal/{0}" -f $_.ADUserName

Displaying block of text

I've done a bit of Googling and can't seem to find an effective method of displaying an entire block of text to the console. I would rather not use the Write-Host command on every line if I need to display a block of code. I'm trying to make an interactive script that's somewhat aesthetic. Is there an example that someone could give me?
PowerShell supports multiline strings, either as here-strings:
Write-Host #"
Some text you
want to span
multiple lines.
"#
or regular strings:
Write-Host "Some text you
want to span
multiple lines."
In addition to Ansgar's examples, Write-Host accepts an array too.
'one','two','three' | Write-Host
So whether your multi-line string is a single string, or an array of lines, it will still work as expected with a single Write-Host call:
Get-Content mycode.txt | Write-Host
Get-Content mycode.txt -Raw | Write-Host

Iteration over inline-initialized array?

I'm new to PowerShell, and have stumbled across some behavior I can't explain while trying to do something fairly straightforward. I have a few variables containing paths within the file system, and I want to make sure that they all have trailing slashes (and add them if they're missing).
# append trailing slash if not present
$engineXCopyPath, $engineXBackupPath, $enlistmentBuildTargetPath | ForEach-Object
{
Write-Host "hi" #where I would check the last character and add a \ if it weren't
}
When running my script, this code keeps prompting for Process[_n_] until I give it no input, in which case it prints the entire contents of the line rather than executing it.
As far as I know, it should be iterating over the three items fed to it, printing "hi" for each one. I'm not sure why it's prompting for any input (not to mention why it stops when I give it blank input), nor do I know why it's printing "Write-Host "hi" #where I would check the last character and add a \ if it weren't" instead of just "hi".
Thanks for your help!
You need to include the opening brace on the same line as ForEach-Object:
$engineXCopyPath, $engineXBackupPath, $enlistmentBuildTargetPath | ForEach-Object {
Write-Host "hi" #where I would check the last character and add a \ if it weren't
}
Otherwise, PowerShell is prompting you for the Process input scriptblocks that are required for ForEach-Object. Then it is interpreting the braces as the creation of a ScriptBlock and printing the contents.

Powershell Add-Content -Value with more than one parameter

Okay someone suggested that I start a new question because my original question was solved but I have another question which belongs to my problem from before.
My first problem was that I wanted to write text in a txt file using double quotes. That is solved. My next problem / question is how can I work with more than one parameter in Add-Content -Value?
Here is an example:
Add-Content -Value '"C:\Program Files (x86)\Fraunhofer IIS\easyDCP Creator+\bin\easyDCP Creator+.exe" "-i C:\Users\Administrator\Desktop\dcp_bearbeitet\$title\$title.txt" "-o" "C:\Users\Administrator\Desktop\output_dcp\$title"'
In this case parameter $title stands for the title of the video clip I am working on and I do not know the title when I am working on it, that is why I am using this parameter. But when I am running my script, power-shell totally ignores my parameter. So I tried it again with single quotes around the parameter for example:
... "-i C:\Users\Administrator\Desktop\dcp_bearbeitet\'$title'\'$title'.txt" ...
And then power-shell does not even perform my script. So maybe somebody knows how I can work with parameters in Add-Content -Value?
You can pass arrays into Add-Content.
$string_array = #(
"`n",
"line1",
"line2",
"line3",
'"line4"',
"li`"ne`"5"
)
$string_array | Add-Content file.ext
The parameter -Value can also take an array directly:
Add-Content -path cake.txt -value #('some "stuff"',"more `"backticked`" stuff","hello world")
You have two competing requirements:
you want to substitute a variable into the command you are building so you need to use double quotes
you want to include double quotes in the output, so you either have to escape them or use single quotes round the string.
One way is to use a here-string, i.e. #"..."# to delimit the string instead of just using ordinary quotes:
$value = #"
"C:\Program Files (x86)\Fraunhofer IIS\easyDCP Creator+\bin\easyDCP Creator+.exe" -i "C:\Users\Administrator\Desktop\dcp_bearbeitet\$title\$title.txt" -o "C:\Users\Administrator\Desktop\output_dcp\$title"
"#
Add-Content -Value $value
That should work for you. I separated it out from Add-Content not because it wouldn't work in-place, but because there is less scope for confusion to do one thing at a time. Also if you build the value up separately you can add a temporary Write-Host $value to quickly check you have the string exactly as you want it.
Another way is simply to escape the enclosed quotes:
$value = "`"C:\Program Files (x86)\Fraunhofer IIS\easyDCP Creator+\bin\easyDCP Creator+.exe`" -i `"C:\Users\Administrator\Desktop\dcp_bearbeitet\$title\$title.txt`" -o `"C:\Users\Administrator\Desktop\output_dcp\$title`""
Add-Content -Value $value
but that does get messy.
Other options would be to build up the string in small chunks, or to use a different character instead of the double quotes inside the string and then do a replace to turn them into the quotes, but either of these is messy. I would go for the "here-string" solution.

Formatting a Powershell string containing hashtable values

The answer to this is likely to be trivial, but I have spent half an hour and still can't work it out.
Assume I have a the following hashtable:
$hash = #{face='Off';}
What I have tried to do, is output the value of "face" along side some other string elements.
This works:
Write-Host Face $hash['face']
=> Face Off
However, this doesn't:
Write-Host Face/$hash['face']
=> Face/System.Collections.Hashtable[face]
Somehow the lack of a space has affected the operator precedence - it is now evaluating $hash as a string, the concatenating [face] afterwards.
Trying to solve this precedence problem, I tried:
Write-Host Face/($hash['face'])
=> Face/ Off
I now have an extra space I don't want.
This works, but I don't want the extra line just to reassign:
$hashvalue = $hash['face']
write-host Face/$hashvalue
=> Face/Off
Any idea how to get this working as a one-liner?
Sure, use a subexpression:
Write-Host Face/$($hash['face'])
Generally, I'd just use a string, if I need precise control over whitespace with Write-Host:
Write-Host "Face/$($hash['face'])"
Yes, in this case you need a subexpression again, but more because you simply can't include an expression like $foo['bar'] in a string otherwise ;-)
By the way, $hash.face works just as well with much less visual clutter.
In such cases, and more so if there are more variables involved, I prefer using the string formatting. While in this case you can live with the $(..), be aware that string formatting will remove lot of doubt, cruft and improves readability:
write-host ("Face/{0}" -f $hash['face'])
In addition to using sub expressions as Joey showed you can:
Use string formatting:
Write-Host ('Face/{0}' -f $hash.face)
This will stick the value of face key in the place of {0}
Use string concatenation:
Write-Host ('Face/' + $hash.face)
Both of those require an expression to be evaluated which outputs a string which is used as Write-Host's Object parameter.
Another option is to insert your slash with the -Separator option of Write-Host:
$hash = #{Face="off"}
Write-Host ("Face",$hash.Face) -Separator '/'