How to compare integers on fish shell? - fish

There isn't much documentation on fish. I need to know if
date '+%k' is greater than 8
How do I do it? Thanks.

You can use the test fish builtin, like:
if test (date +%k) -gt 8
...
end

test or [ are the way you would do this. This is true of all shells, since these are external commands.
if [ (date '+%k') -ge 8 ]
echo "It's larger!"
end

Unlike in traditional languages, the if operator in fish works on exit status of commands. Therefore an additional command test is used to translate logical/mathematical operations into exit status codes.
here are some examples:
count $argrv # returns 0
test (count $argrv) -eq 0 # returns 0, which is evaluated as TRUE by if
test (count $argrv) -eq 1 # returns 1, which is evaluated as FALSE by if
here's how you check if the hour is greater then 8
function testIf
if test (date '+%k') -gt 8
echo "yes"
else
echo "no"
end
end

Related

How can I set a variable in a conditional statement?

I have a script that checks the health of a pc by parsing through log files looking for indicators of compromise. If the script finds a certain event id it returns a normalized message. The end goal is to do math on these returns- this will generate a health score for that PC.
What I need to know is how set a variable (say X with a value of 1) if the event id is found, and set the same variable (say X with a value of 2) if the event id is not found. If I just set both variables in the script -in their respective if/else blocks, won't the last variable always overwrite the first regardless of the condition?
Unfortunately PowerShell doesn't have a conditional assignment statement like Perl ($var = (<condition>) ? 1 : 2;), but you can assign the output of an if statement to a variable:
$var = if (<condition>) { 1 } else { 2 }
Of course you could also do the "classic" approach and assign the variable directly in the respective branches:
if (<condition>) {
$var = 1
} else {
$var = 2
}
The second assignment doesn't supersede the first one, because only one of them is actually executed, depending on the result of the condition.
Another option (with a little more hack value) would be to calculate the values from the boolean result of the condition. Negate the boolean value, cast it to an int and add 1 to it:
$var = [int](-not (<condition>)) + 1
In Powershell 7 you can use the ternary operator:
$x = $true ? 1 : 2
echo $x
displays 1.
What you may want however is switch, e.g.,
$in = 'test2'
$x = switch ($in) {
'test1' {1}
'test2' {2}
'test3' {4}
}
echo $x
displays 2.
A little example that can help to understand.
PowerShell script:
$MyNbr = 10
$MyMessage = "Crucial information: " + $(
if ($MyNbr -gt 10) {
"My number is greater than 10"
} elseif ($MyNbr -lt 10) {
"My number is lower than 10"
} else {
"My number is 10"
}
)
Write-Host $MyMessage
Output:
Crucial information: My number is 10
If you change the MyNbr variable, you will have a different result depending on conditions in the if statements.
You actually can evaluate a condition and assign the result to a variable. It's the closest you get to a ternary operator in PowerShell. I find it makes it simpler to do complicated conditional statements. It makes it easier to read and change them. Here's an example:
$theEventIdIWant = 6000
$eventId = 5000
$correct = $eventID -eq $theEventIdIWant
if($correct) {$true} else {$false}

perl how to force boolean to 0/1

I'm trying to get a 0 or 1 in a value for true/false. Here's the code:
use strict;
my %h = (Y => "y");
my $bool_x = 1 & exists $h{X};
my $bool_y = 1 & exists $h{Y};
print("x $bool_x y $bool_y\n");
I needed to add the "1 &" to force it to not be the empty string. Is there a better way to do this? I realize that it's an artifact of the way perl prints the false value, but I need it to be a 0 not the empty string.
The most efficient way to do this is just:
$bool || 0
Your code is far from clear. The & operator is a bitwise operator that behaves differently on numbers and strings, but exists returns a value that will obligingly be the number zero or the empty string depending on what is required of it. perldoc perlop has this to say
Although no warning is currently raised, the result is not well defined when this operation is performed on operands that aren't either numbers (see Integer Arithmetic) nor bitstrings (see Bitwise String Operators)
So because the result of exists is one such value your code is on shakey ground
There is no need to write something arcane, and if you want to represent Perl's internal true and false values by a different pair of values then the conditional operator is the correct choice
my $bool_x = exists $h{X} ? 1 : 0
I believe that's the most readable without being verbose, and that's all that matters here. It's also applicable to any other pair of values that you may choose, such as
my $bool_x = exists $h{X} ? 'Y' : 'N'
There are many ways to "numify" a true/false value.
If $var can contain 1 or any false value, all of these will evaluate to either "0" or "1":
0 + $var
0 | $var
$var || 0
1 * $var
1 & $var (you discovered this one, already)
chr(48+$var)
sprintf "%d", $var
These constructions return a 0/1 value when $var can contain any true or false value:
0 + !!$var ( !! true => 1, !! false => "" )
1 - !$var
$var ? 1 : 0

Illegal Number when Comparing floats

if [ 3 -lt 6 ]; then
echo "It works with ints"
fi
if [ 3.0 -lt 6.0 ]; then
echo "It works with floats"
else
echo "It doesn't work with floats"
fi
Comparing the integers in an "if" works just fine.
But it doesn't work when I do the same thing with floating point numbers, and gives me this output:
+ [ 3.0 -lt 6.0 ]
/tmp/hudson7259224562322746826.sh: 11: [: Illegal number: 3.0
+ echo It doesn't work with floats
It doesn't work with floats
As per the bash manpage (my emphasis at the end):
arg1 OP arg2 : OP is one of -eq, -ne, -lt, -le, -gt, or -ge. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers.
In other words, bash has no native support in comparing floating point values.
If you really want to handle floating point, you're better off choosing a tool that does support it, such as bc:
n1=3.0 ; n2=6.0
if [[ $(echo "${n1} < ${n2}" | bc) -eq 1 ]] ; then
echo ${n1} is less than ${n2}
fi

Use of diff command from tcl script captures error 'child process exited abnormally'

In tcl script I am using diff command to compare the files line by line
if {[catch {eval exec "diff /tmp/tECSv2_P_HTTP_XHDR_URL_FUNC_12.itcl /tmp/tempReformat"} results]} {
puts "$results"
}
Output of diff command is obtained properly but it catches error 'child process exited abnormally'
Output:
==>tclsh diffUsingScript
992c992
< fail "Redirection is not reflected in css messages"
---
> fail "Redirection is not reflected in css messages"
child process exited abnormally
So whats going wrong due to which this error is obtained. I want diff operation to be error free in my tcl script
From my diff(1): "Exit status is 0 if inputs are the same, 1 if different, 2 if trouble."
Since non-zero returns are the usual way to report errors in shell scripts, tcl and diff disagree on the meaning of the return result. It's probably really convenient for writing shell scripts to know whether or not two files are different from the return value, but I don't see any mechanism to disable that from the manpage. (I'd rather use cmp -q for just getting whether or not two files are different, not sure why the diff people made the decision they did.)
But you can bludgeon this into working by appending ; true to your command.
A more artful way to make it work would be to error only on an exit code of 2: diff foo bar ; if [ $? -ne 2 ]; then true ; else false; fi;
Check the results with different filenames and echo $? after each test to see which ones are returning 0 (from true) and which ones are returning 1 (from false).
The way to handle this in Tcl is:
set rc [catch {exec diff f1 f2} output]
if {$rc == 0} {
puts "no difference"
} else {
if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
if {[lindex $::errorCode 2] == 1} {
puts "difference"
# show output without "child process exited abnormally" message
puts [string replace $output end-31 end ""]
} else {
puts "diff error: $output"
}
} else {
puts "error calling diff: $output"
}
}
See the discussion on the Tcl Wiki exec page.

Using Powershell's bitwise operators

I'm looking for example of how I would solve the scenario below:
Imagine my printer has the following property for "Status"
0 -Offline
2 -Paper Tray Empty
4 -Toner Exhausted
8 -Paper Jam
When I query status it returns a value of 12. I can obviously see that this means the printer has the Toner Exhausted and a Paper Jam, but how would I work this out with Powershell?
Thanks
The boolean bitwise and operator in Powershell is -band.
Assume you define your values and descriptions in a hashtable, and have the value of 12 from the printer:
$status = #{1 = "Offline" ; 2 = "Paper Tray Empty" ; 4 = "Toner Exhausted" ; 8 = "Paper Jam" }
$value = 12
Then, this statement will give you the textual descriptions:
$status.Keys | where { $_ -band $value } | foreach { $status.Get_Item($_) }
You could define the enum in Powershell, but the above works just as well, and defining enums in Powershell seems like a lot of work.
Here is an article, that talks about how to use the bitwise operators in Powershell.
You can let PowerShell do more of the work for you. Here's an example using System.IO.FileOptions:
PS> [enum]::GetValues([io.fileoptions]) | ?{$_.value__ -band 0x90000000}
RandomAccess
WriteThrough