How does Powershell display variable operation work? - windows

In powershell
$a = 4;
$a
will write 4 to the output stream.
Write-Ouput $a
writes 4 to output stream
Can you explain which operation is better performance wise if all I want to do is write variables to output stream?

If you just want to see what's in your variable, you should use a dollar sign with the name of your variable. This is most likely the fastest method to display the value of the variable.
UPDATE
Short answer: You should use just $a in order to write data in the output stream. It's the fastest way to do that.
Long answer with explanation:
If you write something like $a, then it goes directly to the output stream of the current PowerShell process, in other words, it goes to the output pipeline. This is because in PowerShell you have in general only three types of possible statements:
Definition statement: They are everything that you can define in your code for further use like functions or classes.
Assignment statement: You assign a value to a variable.
Putting-in-the-pipeline statement: everything else except 1 and 2.
Example for definition statements:
Function foo($bar)
{
#do stuff here
}
Example for assignment statements:
$foo = 'bar'
Example for putting-in-the-pipeline statement:
It is exactly what you asked! If you write $a, then it will be written to the output pipeline. That’s it.
Now about Write-Output. According to this code from the official PowerShell repository, it's just a wrapper for another PowerShell Cmdlet, namely for WriteObject. Therefore, the invocation of Write-Output costs more time then the invocation of WriteObject.
As Lee_Dailey mentioned in the first comment to your question, there is a wonderful article Let’s Kill Write-Output written by Mark Kraus in his blog. At first sight it may seem that it doesn't have much to do with your question, but this article explains what happens with objects that you wrote in your script and when they are not surrounded with different "printing functions" like Write-Out. There you can also find examples of how to "bypass" the use of the Write-Out in different situations that it brings advantages in performance.
I also recommend to read these two articles from Microsoft's DevBlogs:
Understanding Streams, Redirection, and Write-Host in PowerShell
Weekend Scripter: Welcome to the PowerShell Information Stream
They will definitely help to understand how streams are implemented and how they work in PowerShell.

Related

How does $RANDOM work in Unix shells? Looks like a variable but it actually assumes different values each time it's called

I recently used the $RANDOM variable and I was truly curious about the under-the-hood implementation of it: the syntax says it's a variable but the behavior says it's like a function as it returns a different value each time it's called.
This is not "in Unix shells"; this is a Bash-specific feature.
It's not hard to guess what's going on under the hood; the shell special-cases this variable so that each attempt to read it instead fetches two bytes from a (pseudo-) random number generator.
To see the definition, look at get_random in variables.c (currently around line 1363).
about the under-the-hood implementation of it
There are some special "dynamic variables" with special semantics - $PWD $HOME $LINENO etc. When bash gets the value of the variable, it executes a special function.
RANDOM "variable" is setup here bash/variables.c and get_random() just sets the value of the variable, taking random from a simple generator implementation in bash/random.c.

Is there a way to get the result of the last operation into a variable

Sometimes when using the php artisan tinker console I do something like the following:
$int->groupBy('tracking_code')->toArray();
instead of:
$a = $int->groupBy('tracking_code')->toArray();
If the operation is very complex and/or is on lots of records, it can be a pain to repeat with the variable assignment. So my question is whether the result of the last command is stored anywhere so I can manipulate it without having to wait for the operation to complete a second time?
Tinker uses PsySH as the REPL.
$a = $_
$_ is a magic variable that holds the result of the last successful execution.
You can find documentation for PsySH on its website:
PsySH

In Bash, Why `then` is needed in the conditional constructs?

The conditional construct of if command looks like this:
if TEST-COMMANDS; then
CONSEQUENT-COMMANDS;
[elif MORE-TEST-COMMANDS; then
MORE-CONSEQUENTS;]
[else ALTERNATE-CONSEQUENTS;]
fi
And the loop construct of while command looks like this:
while TEST-COMMANDS; do CONSEQUENT-COMMANDS; done
I was wondering why then is needed in if command but not in while command? Why couldn't it be ommited?
do in the while syntax serves a similar purpose to then in the if syntax. They both signify the start of the body of the statement - differentiating it from the condition part of the statement.
The if conditional statement is a compound statement in the shell. The if & then sections of the statement are executed as two parts, the then section is only invoked if the if section ends with an exit status of 0. Both sections may contain multiple statements; therefore, a semi-colon alone is insufficient to separate these sections.
Like #shibley is saying in his answer, the do and then words are used to indicate the beginning of the block of actions to perform.
I have done some research and could not find the historical reasons, so I am going to guess the logical ones. It might be too subjective, so do not hesitate to comment your impressions below.
The bash syntax is quite "symmetrical": Whenever you have an case you finish it with esac. Also, it was designed in a very human way, so it is easily understandable.
That said, if you are in a while loop, it means that you are going to do something while a condition is true. Then, when it is not true anymore you are done.
However, in an if condition, you are saying that if something happens, then something needs to be executed.
In short: do and then are human-readable ways to indicate the same, that is, the beginning of a block of commands to be performed upon a while or if condition.

Bash: No return value when calling a function

I'm new to stackoverflow and bash scripting, so go easy on me! I've been struggling with a bash script I've been writing: when I try to call a function 'main' from my script like so:
variable=$("main -t $path/$i")
I get the error "main -t ./folder: No such file or directory"; any ideas?
Thanks in advance!
EDIT: Thanks Jkbkot, I'm now calling it like this:
variable=$(main -t "$path/$i")
The original error is sorted but something is still up: 'variable' seemingly isn't being assigned the value echoed in the function, though calling the function manually prints the correct value. Why might this happen?
EDIT: It seems I'm calling and echoing correctly, but when calling 'main' it seems to behave differently when called recursively to the initial call. For example it runs fine up to:
variable=$(main -t "$path/$i") #A line within 'main'
Then begins again, as expected, but this time it stops as soon as it comes across a 'break', apparently breaking out of the entire function call rather that just the 'case' it's currently in. Is there some quirk to 'break' in bash that I'm unaware of?
NOTE: Unfortunately, the script is an assignment from my university, and many of its students and teachers use this website, so publicly posting my solution would likely have negative consequences.
You have to call it without the quotes:
variable=$(main -t $path/$i)
and as #janos says, you might need the quotes around the variables in case they might contain spaces, etc.:
variable=$(main -t "$path/$i")

Why are bash variables 'different'?

Is there some reason why bash 'variables' are different from variables in other 'normal' programming languages?
Is it due to the fact that they are set by the output of previous programs or have to be set by some kind of literal text, ie they have to be set by the output of some program or something outputting text through standard input/output or the console or such like?
I am at a loss to use the right vocabulary, but can anyone who can understands what I trying to say and perhaps use the right words or point me some docs where I can understand bash variable concepts better.
In most languages, variables can contain different kinds of values. For example, in Python a variable can be a number that you can do arithmetics on (a-1), an array or string you can split (a[3:]), or a custom, nested object (person.name.first_name).
In bash, you can't do any of this directly. If I understood you right, you asked why this is.
There are two reasons why you can't really do the same in bash.
One: environment variables are (conventionally) simple key=value strings, and the original sh was a pretty thin wrapper on top of the Unix process model. Bash works the same, for technical and compatibility reasons. Since all variables are (based on) strings, you can't really have rich, nested types.
This also means that you can't set a variable in a subshell/subscript you call. The variable won't be set in the parent script, because that's not how environment variables work.
Two: Original sh didn't separate code and data, since this makes it easier to work with interactively. Sh treated all non-special characters as literal. I.e. find / -name foo was considered four literal strings: a command and three arguments.
Bash can't just decide that find / -name now means "the value of the variable find divided by the negated value of variable name", since that would mean everyone's find commands would start breaking. This is why you can't have the simple dereferencing syntax other languages do.
Even $name-1 can't be used to substract, because it could just as easily be intended as part of $name-1-12-2012.tar.gz, a filename with a timestamp.
I would say it has to do with Bash functions. Bash functions cannot return a value, only a status code.
So with Bash you can have a function
foo ()
{
grep bar baz
}
But if you try to "save" the return value of the function
quux=$?
It is merely saving the exit status, not any value. Contrast this with a language such as Javascript, functions can actually return values.
foo ()
{
return document.getElementById("dog").getAttribute("cat");
}
and save like this
quux = foo();

Resources