Reverse order of a string - bash

I want to "reverse" the order of the four octets (bytes) that make up an ip address.
Suppose I have this ip:
202.168.56.32
I need to convert into:
32.56.168.202
and then ultimately remove the first octet in the reversed ip. Final result:
56.168.202
My attempts:
echo 202.168.56.32 | rev
But it's returning :
23.65.861.202

This should do the trick:
echo 202.168.56.32|awk -F. '{print $3"."$2"."$1}'
You could also do it with bash arrays:
ip=202.168.56.32
parts=(${ip//./ })
echo ${parts[2]}.${parts[1]}.${parts[0]}

Or you could use sed.
echo 202.168.56.32 | sed -e 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\4.\3.\2.\1/g'

Related

How to save to the var, only one from the output

Im writing a script that executes dig command on 2 domains, and after next cmd is host on output.
And always i will get for exmaple:
findUserServer=for r in $(dig +short $login.example.COM && dig +short $login.example.ORG); do host $r|awk '{print $NF}';done | awk -F "." '{print $1}';
1 output: >> asdf02 example
asdf02 - its a server name, its always same name starts "asdf".
Question: Have you any idea how to save to the variable only asdf02?
question+: asdf02 woudln't be always first, could be example asdf02
Should i do maybe a sed which looks on 4 first characters? If it's "asdf", then: [...]
Try not to pipe awk commands into each other and so:
for r in $(dig +short $login.example.COM && dig +short $login.example.ORG); do host $r;done | awk -F [.\ ] '/asdf02/ { print $10 }'
We use both a space and . as delimiters and then pattern match the output for the occurance of asdf02. If we find is, we print the address.
Run that through shellcheck.net ...
Try this.
findUserServer="$( for end in COM ORG; do
host $( dig +short $login.example.$end );
done | sed -n '/ asdf/{ s/^.* //; s/[.].*//; p; }' )"
This will run 2 digs and pipe the collective output through sed,
which will ignore lines that don't have asdf, and strip the matches clean for you.
Let me know if I missed details, because I don't have those exact values available.

Take substring and remove period in bash

I have a string for example : 192.168.22.13
I want to take a substring and remove the periods such that I get 2213 only from this string which i can use as a custom port number.
Is there anyway I can do this in a single bash command instead of doing:
e1=${1//.}
e1Port=${e1:6}
bash string directives don't allow nested expressions.
You may use awk for a single command:
s='192.168.22.13'
port=$(awk -F '.' '{print $3 $4}' <<< "$s")
echo "$port"
2213

Reverse DNS-style string

In a script running in a Debian environment, what is a good way to reverse a DNS-style string?
For example, if my script has:
example.org
What would be a good way to reverse it, so that the string would read:
org.example
A longer example:
www.example.org
should reverse to:
org.example.www
You could use an iterative approach to build a reversed address:
Initialize the reversed result to empty string
While the string contains .
Extract the last segment chopping off everything from the start until a dot using parameter expansion ${var##*.}
Chop off the last segment with another parameter expansion ${var%.*}
Append to the reversed result the previously saved last segment
Here's one way to implement using pure Bash features:
rdns() {
local s=$1
local reversed last
while [[ "$s" == *.* ]]; do
last=${s##*.}
s=${s%.*}
reversed=$reversed$last.
done
reversed=$reversed$s
echo "$reversed"
}
rdns example
rdns example.org
rdns www.example.org
Outputs:
example
org.example
org.example.www
this might do
s='www.example.org'
echo $s | tr '.' '\n' | tac | paste -sd.
You can try
sed -E 's/\./\n/g;s/$/\n/;:A;s/([^\n]*)\n(.*)(\n)(.*)/\2\3.\1\4/;tA;s/\n//'

Bash Replace Variable IP Address with Network

I have an IP address set in a variable that I'd like to convert into a network address.
This only works for a single digit:
echo '192.168.1.2' | sed 's/.$/0/' => 192.168.1.0
echo '192.168.1.22' | sed 's/.$/0/' => 192.168.1.20
echo '192.168.1.223' | sed 's/.$/0/' => 192.168.1.220
I need a method to return the same network value if the last digit(s) change, i.e:
myip="192.168.1.2" => "192.168.1.0"
myip="192.168.1.22" => "192.168.1.0"
myip="192.168.1.223" => "192.168.1.0"
How can I replace any IP address with it's network address like above?
Pure bash solution without external commands:
echo "${myip%.*}.0"
for example:
$ echo "$myip"
192.168.1.22
$ echo "${myip%.*}.0"
192.168.1.0
Using sed
echo '192.168.1.2' | sed 's/\.[^.]*$/.0/'
sed 's/\.[^.]*$/.0/' <<< 192.168.1.22 # echo + pipe is not needed here
Logic: Replace everything from last . till end with .0
Using awk
awk -F. '{$NF=0}1' OFS=. <<< 192.168.1.22
awk '{$NF=0}1' FS=. OFS=. <<< 192.168.1.22
Logic: Split string with . and set last field to 0.
pure bash:
{ IFS=. read a b c _; echo $a.$b.$c.0; } <<< 192.168.1.22
( IFS=.; read -a ip; ip[3]=0; echo "${ip[*]}"; ) <<< 192.168.1.22
Logic: Read 4 parts of the IP address in 4 variables. Print first 3 and a 0.
Or by using a bash array, if you don't want to clutter environment with too many variables.
You can do this with awk using:
pax> awk -F. '{print $1"."$2"."$3".0"}' <<<12.34.56.78
12.34.56.0
With sed, it's possible to just replace all the digits at the end:
pax sed 's/[0-9]*$/0/' <<<12.34.56.78
12.34.56.0
However, all of those result in an extra process being started up, not something you need to worry about for a few IP addresses but it will make a difference if you're converting many of them.
To do it within bash only (not requiring another process), you can use:
pax> ip=12.34.56.78
pax> echo ${ip%.[0-9]*}.0
12.34.56.0
It is very simple to do with pure bash:
myip="192.168.1.2 "; echo "$myip ==> ${myip%.*}.0"
myip="192.168.1.22 "; echo "$myip ==> ${myip%.*}.0"
myip="192.168.1.223"; echo "$myip ==> ${myip%.*}.0"
Results in:
192.168.1.2 ==> 192.168.1.0
192.168.1.22 ==> 192.168.1.0
192.168.1.223 ==> 192.168.1.0
However, that is assuming the network has a CDIR of 24 (192.168.1.2/24).
If that is not what you will always use, this idea will break.

Get length of string from grep does not work

I try to get the length of a string like this (bash in linux):
VAR= grep "test" file.txt
VARlength= ${#VAR}
For some reason the length is always zero, even if the string "test" is inside file.txt
Can someone explain me how to get the length of VAR and what is wrong there?
don't leave space before and after the =
you need command substitution: var=$(command)
Use $( ):
VAR=$(grep "test" test.txt)
VARlength=${#VAR}
If you like it's also possbile to use bc and wc to get the result:
VARlength=$(echo "var="$(grep "2" foo | wc -c;)";--var" | bc)
This will count the chars inside the match (wc -c) and then subtract 1 using bc, because you don't want to count the newline.

Resources