Filtered Windows comand works on it's own inside WSL, but not in a script - bash

I have this command which returns an IP successfully:
user#laptop:~$ systeminfo.exe | sed -n '/Connection Name: vEthernet (WSL)/,+4p' | egrep --word-regexp '\[01\]:' | awk '{print $2}'
172.22.0.1
I am trying to concatenate and export an environmental variable DISPLAY using a script with this content:
LOCAL_IP=$(systeminfo.exe | sed -n '/Connection Name: vEthernet (WSL)/,+4p' | egrep --word-regexp '\[01\]:' | awk '{print $2}')
export DISPLAY=$LOCAL_IP:0
But after this script runs, DISPLAY doesn't look like expected:
user#laptop:~$ echo $DISPLAY
:02.22.0.1
I was expecting an answer 172.22.0.1:0. What went wrong?

LOCAL_IP appears to have a trailing \r; od -c <<< "${LOCAL_IP}" should show the value ending in a \r
One fix using parameter substitution:
$ export DISPLAY="${LOCAL_IP//$'\r'/}:0"
$ echo "${DISPLAY}"
172.22.0.1:0
Another option would be to add an additional pipe on the end of OP's current command, a couple ideas (dos2unix, tr -d '\r'); 3rd option modifies the awk script to remove the \r:
systeminfo.exe | sed -n '/Connection Name: vEthernet (WSL)/,+4p' | egrep --word-regexp '\[01\]:' | awk '{print $2}' | dos2unix
# or
systeminfo.exe | sed -n '/Connection Name: vEthernet (WSL)/,+4p' | egrep --word-regexp '\[01\]:' | awk '{print $2}' | tr -d '\r'
# or
systeminfo.exe | sed -n '/Connection Name: vEthernet (WSL)/,+4p' | egrep --word-regexp '\[01\]:' | awk '{gsub(/\r/,"");print $2}'
Another option would be to replace the sed/egrep/awk/tr with a single awk call. If OP wants to go this route I'd recommend asking a new question, making sure to provide the complete output from systeminfo.exe to better understand the parsing requirements.

Related

Shell Scripting array not printing proper values

I have this simple Shell Script where I am searching for ID and Port Number from the file and saving it in Array. However When I try to print them I am not getting expected results. I am looping the array to print the 1st and 2nd element and then increasing by two to print 3rd and 4th element. I also want to print them like each ID Port in separate line, like this:
ID Port
ID Port
My code is:
myarr=($(less radius-req | grep C4-3A-BE-18-C1-2D -B75 | grep '2018-11\|Port' | grep -v User | grep Source -B1 | awk -F "Port:|id=" '{print $2}' )); for ((i=0;i<"${#myarr[#]}";i+=2)) ; do echo $i; printf "%s\n" "${myarr[$i]}" "${myarr[$i+1]}" ; done;
Even If I try to echo the whole array I only see the last element, whereas I could print each individual element without an issue.
$ myarr=($(less radius-req | grep C4-3A-BE-18-C1-2D -B75 | grep '2018-11\|Port' | grep -v User | grep Source -B1 | awk -F "Port:|id=" '{print $2}' )); echo ${myarr[#]}
45210
$ myarr=($(less radius-req | grep C4-3A-BE-18-C1-2D -B75 | grep '2018-11\|Port' | grep -v User | grep Source -B1 | awk -F "Port:|id=" '{print $2}' )); echo ${myarr[0]}
19
$ myarr=($(less radius-req | grep C4-3A-BE-18-C1-2D -B75 | grep '2018-11\|Port' | grep -v User | grep Source -B1 | awk -F "Port:|id=" '{print $2}' )); echo ${myarr[1]}
45210
$ myarr=($(less radius-req | grep C4-3A-BE-18-C1-2D -B75 | grep '2018-11\|Port' | grep -v User | grep Source -B1 | awk -F "Port:|id=" '{print $2}' )); echo ${myarr[2]}
20
$ myarr=($(less radius-req | grep C4-3A-BE-18-C1-2D -B75 | grep '2018-11\|Port' | grep -v User | grep Source -B1 | awk -F "Port:|id=" '{print $2}' )); echo ${myarr[3]}
45210
From the output you give, I suspect that the problem is due to carriage return characters in the radius-req file. My guess is the file is from Windows (or maybe a web download), which uses carriage return + linefeed as a line terminator. Unix uses just linefeed (aka newline) as a terminator, and unix programs will treat the carriage return as part of the content of the line. Net result: you get things like "19<CR>" and "45210<CR>" as array values, and when you print them it prints them all over top of each other.
If I'm right about the problem, it's pretty easy to fix. Just replace less radius-req (which you shouldn't use anyway, see William Pursell's comment) with tr -d '\r' <radius-req. The tr command does character replacements, -d means just delete instead of replacing, and \r is its notation for the carriage return character. Result: it deletes the carriage returns before they have a chance to mess things up.

Pass value from output of one command to sed

I have a file, config.txt with many lines. One line is like this
address=
I am getting the ip address of the machine on which config.txt resides, with
ip addr | grep 'state UP' -A2 | tail -1 | awk '{print $2}' | cut -f1 -d'/'
That code is taken from a Stack Overflow answer.. The output I am getting is an IP address -
192.168.3.260
I would like to replace
address=
in config.txt with
address='192.168.3.260'
Is it possible to do it in one line, i.e.
ip addr | grep 'state UP' -A2 | tail -1 | awk '{print $2}' | cut -f1 -d'/' | <some sed command >
Using grep, cut and awk in a single pipeline is almost always a mistake, since awk can do everything grep can do, and then some. You can extract the IP address with a sed one-liner, like this:
ip addr | sed -n '/state UP/ {n;n;s/ *inet \(.*\)\/.*/\1/p}'
You can also use this approach to build the command you are looking for:
ip addr | sed -n "/state UP/ {n;n;s/ *inet \(.*\)\/.*/s|address=|\&'\1'|/p}"
which prints something like this:
s|address=|&'192.168.3.260'|
And then you can pipe that program to sed:
ip addr | sed -n "/state UP/ {n;n;s/ *inet \(.*\)\/.*/s|address=|\&'\1'|/p}" \
| sed -f - config.txt
sed -i 's/address=/address='$(ip addr | grep 'state UP' -A2 | tail -1 | awk '{print $2}' | cut -f1 -d'/')'/' filename
Where filename is the name of the file in question, the key here is to use indirection i.e. $(ip addr | grep 'state UP' -A2 | tail -1 | awk '{print $2}' | cut -f1 -d'/') and then use this in a sed command placing particular emphasis on the quotation marks. The indirection must side outside of the single quotation marks of the sed command.

Bash grep local IP address and write to file in makefile?

I'm trying to get my local ip with ifconfig and write it to file but for some reason fail to do so.
run:
LOCALIP=$(shell ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | awk '{print $1}') &
echo "var LOCAL_IP = '${LOCALIP}'" > local_ip.js &
It does get the correct IP but for some reason fails to write it to file and file contains only var LOCAL_IP = ''
Could anyone help me and tell what I'm doing wrong?
Two issues: one, each separate command in a Makefile recipe is executed in a separate shell, so you need to "merge" them. Two, you need to double the $ in the echo so that it is sent to the shell, not expanded first by make. This should work:
run:
LOCALIP=$(shell ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | awk '{print $1}'); \
echo "var LOCAL_IP = '$${LOCALIP}'" > local_ip.js
The semicolon and the line-continuation backslash ensure that the entire recipe is executed in the same shell, so that LOCALIP is still set when the echo is run. You could "simplify" this by embedding the command substitution directly in the argument to echo.
run:
echo "var LOCAL_IP = '$(shell ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | awk '{print $1}')'" > local_ip.js
This awk can work:
ifconfig | awk -F: '/inet addr/&& !($2 ~ /127\.0\.0\.1/){gsub(/ .*/, "", $2); print $2}'

Use each line of piped output as parameter for script

I have an application (myapp) that gives me a multiline output
result:
abc|myparam1|def
ghi|myparam2|jkl
mno|myparam3|pqr
stu|myparam4|vwx
With grep and sed I can get my parameters as below
myapp | grep '|' | sed -e 's/^[^|]*//' | sed -e 's/|.*//'
But then want these myparamx values as paramaters of a script to be executed for each parameter.
myscript.sh myparam1
myscript.sh myparam2
etc.
Any help greatly appreciated
Please see xargs. For example:
myapp | grep '|' | sed -e 's/^[^|]*//' | sed -e 's/|.*//' | xargs -n 1 myscript.sh
May be this can help -
myapp | awk -F"|" '{ print $2 }' | while read -r line; do /path/to/script/ "$line"; done
I like the xargs -n 1 solution from Dark Falcon, and while read is a classical tool for such kind of things, but just for completeness:
myapp | awk -F'|' '{print "myscript.sh", $2}' | bash
As a side note, speaking about extraction of 2nd field, you could use cut:
myapp | cut -d'|' -f 1 # -f 1 => second field, starting from 0

Hiding xfce4-panel from command line

Is there a way to hide xfce4-panel from command line. If no any other solutions how to hide it from terminal ?
Regards,
Levon
I got here wondering the same. Apparently there is no direct command, but it's pretty straightforward to write a shell script:
INFO=$(xwininfo -name xfce4-panel)
STATE=$(echo "$INFO" | grep "Map State:" | head -n1 | awk -F: '{print $2}' | xargs)
WID=$(echo "$INFO" | grep "Window id:" | head -n1 | awk -F: '{print $3}' | awk '{print $1}')
if test "$STATE" = "IsViewable"; then
xdotool windowminimize "$WID"
else
xdotool windowmap "$WID"
fi

Resources