Issue
I am looking to a way to leverage null coalescing feature that exists in other language for my script but I can't seem to wrap my expression to accept the first non null value from an expression and a variable in a one line .
Context
I need to check the list of specific inbound open ports from my azure network security group but there are two sources where ports can be defined (all port in one rule [22,80,etc} or one port per rule [rule1=22 , rule2=80 etc])
To make this simple :
I have two variables and they store list of ports in a vertically (Array).how I get the values doesn't matter
- $nsg_port_a (ports found on multiport rules)
- $nsg_port_b (ports found on all single port based rules)
nsg_port_a=$(az network nsg show -g $My_resourceG -n $My_SG --query securityRules[?direction==\`Inbound\`].destinationPortRange -o tsv)
nsg_port_b=$(az network nsg show -g $My_resourceG -n $My_SG --query securityRules[?direction==\`Inbound\`].destinationPortRanges[] -o tsv)
# echo $nsg_port_a
22 80 443
# echo $nsg_port_b
80 443
-I just need to confirm for example that port 22 occurs once in either variables.
- i.e if 22 is present in the first variable array and not the second then $ssh=22 .
example -> SSH port:
pseudo code : first non null wins
ssh = { print 22 if 22 is in nsg_port_a || print 22 if 22 is on nsg_port_b}
I first tried to check if ssh port is open separately in the first variable. then using the coalescing logic check if the second nsg_port_b contains 22 or is null (if both are null it's fine). if it exist in any of them the value stays ssh=22.
first check
with $nsg_port_a = 22 80 443
# ssh=$(echo $nsg_port_a | awk 'match($0,/22/) {print substr($0,RSTART,RLENGTH)}')
# echo $ssh
22
second check I tried the below but I have syntax errors
$nsg_port_b = 80 442
# ssh=${echo $nsg_port_b | awk 'match($0,/22/) {print substr($0,RSTART,RLENGTH)}':-${ssh}}
-bash: ${echo $nsg_port_b | awk 'match($0,/22/) {print substr($0,RSTART,RLENGTH)}':-${ssh}}: bad substitution
Note :
I am sure I can do the check from both variables in one line. but I can't get which syntax to use.
i.e take the first non null value the both vars checks in a one liner.
ssh=${`echo $nsg_port_a | awk 'match($0,/22/) {print substr($0,RSTART,RLENGTH)}'`: `echo $nsg_port_b | awk 'match($0,/22/) {print substr($0,RSTART,RLENGTH)}'`}
thanks in advance koss
EDIT
My bad my sample was showing the values displayed in one row (tab separated) which is right even though the content was new line separated when I ran the $(az network...) request the encapsulation of the values in the variable flattens the list to one row if I echo nsg_port_a without "
. I am aware that 22 can be contained in port 422 but I'm only focused in popular values like 22/80/443/3389.
Solution
I now think the problem is you don't actually have blank chars between your ports as shown in your question but instead have newlines or tabs. Given that, this will work no matter what the white space is:
$ nsg_port_a='22 80 443'
$ nsg_port_b='80 443'
$ [[ " $nsg_port_a $nsg_port_b " =~ [[:space:]]22[[:space:]] ]] && ssh=22
$ echo "$ssh"
22
Answered By - Ed Morton