How do I get sed to use a user input variable? - bash

It doesn't seem like sed is aware of the $IP variable.
How can I get the following to work?
read -p "Please enter the line number with the IP you wish to block from accessing the Internet? " IP
echo $IP
IP_LINE_NUMBER=`nmap -n -sn 192.168.3.0/24 -oG - | awk '/Up$/{print $2}' | sed '$IPq;d'`
echo $IP_LINE_NUMBER

You have to use double quotes and put {} around IP:
ip_line_number=$(nmap -n -sn 192.168.3.0/24 -oG - | awk '/Up$/{print $2}' | sed "${IP}q;d")
Note: you need command substitution $(...) to get the output into your variable
See also:
Difference between single and double quotes in Bash
Correct Bash and shell script variable capitalization

Related

User input into variables and grep a file for pattern

H!
So I am trying to run a script which looks for a string pattern.
For example, from a file I want to find 2 words, located separately
"I like toast, toast is amazing. Bread is just toast before it was toasted."
I want to invoke it from the command line using something like this:
./myscript.sh myfile.txt "toast bread"
My code so far:
text_file=$1
keyword_first=$2
keyword_second=$3
find_keyword=$(cat $text_file | grep -w "$keyword_first""$keyword_second" )
echo $find_keyword
i have tried a few different ways. Directly from the command line I can make it run using:
cat myfile.txt | grep -E 'toast|bread'
I'm trying to put the user input into variables and use the variables to grep the file
You seem to be looking simply for
grep -E "$2|$3" "$1"
What works on the command line will also work in a script, though you will need to switch to double quotes for the shell to replace variables inside the quotes.
In this case, the -E option can be replaced with multiple -e options, too.
grep -e "$2" -e "$3" "$1"
You can pipe to grep twice:
find_keyword=$(cat $text_file | grep -w "$keyword_first" | grep -w "$keyword_second")
Note that your search word "bread" is not found because the string contains the uppercase "Bread". If you want to find the words regardless of this, you should use the case-insensitive option -i for grep:
find_keyword=$(cat $text_file | grep -w -i "$keyword_first" | grep -w -i "$keyword_second")
In a full script:
#!/bin/bash
#
# usage: ./myscript.sh myfile.txt "toast" "bread"
text_file=$1
keyword_first=$2
keyword_second=$3
find_keyword=$(cat $text_file | grep -w -i "$keyword_first" | grep -w -i "$keyword_second")
echo $find_keyword

Extract range of lines using sed

I have defined two variables as follows:
var1=$(unzip -c ./*.zip | grep -n "Channel8"| cut -f1 -d":")
var2=$(unzip -c ./*.zip | grep -n "Channel10"| cut -f1 -d":")
I have a very big file and I would like to extract the range of lines between $var1 and $var2 using sed. I am trying the following
sed -n '/"$var1","$var"2p' $(unzip -c ./*.zip)
But with no success. Could you give an explanation why and how to fix it? Thanks.
You can use:
unzip -c ./*.zip | sed -n "$var1,$var2 p"
Fixes are:
Not using single quotes around shell variable
Removal of leading / from sed command
Use of pipeline instead of command substitution
Variables aren't expanded inside single quotes. Also, you need to pipe the output of unzip to sed, not use it as command-line arguments.
unzip -c ./*.zip | sed -n "${var1},${var2}p"
But it seems like you're doing this the hard way, reading the zip file 3 times. Just use the pattern you want to match as the range:
unzip -c ./*.zip | sed -n '/^extracting:.*Channel8/,/^extracting:.*Channel10/p'
Use double quotes to expand the vars:
sed -n "${var1},${var2}p" $(unzip -c ./*.zip)

using makefile variable in sed command [duplicate]

This question already has an answer here:
Sed command in makefile
(1 answer)
Closed 6 years ago.
I have tried putting the following command in makefile.
#get Local Ip Address
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}') &
#get Web Url from User
#read -p "Enter Web Url:" weburl; \
sed -e "\|$LOCALIP $weburl|h; \${x;s|$LOCALIP $weburl||;{g;t};a\\" -e "$LOCALIP $weburl" -e "}" hosts.txt
When I try to execute the command, I expected to get the sed command like following:
sed -e "\|192.168.5.1 www.weburl.com|h; \${x;s|192.168.5.1 www.weburl.com||;{g;t};a\\" -e "192.168.5.1 www.weburl.com" -e "}" hosts.txt
But, I get the following,
sed -e "\|/s/$/OCALIP eburl|h; \" hosts.txt
In Makefiles, variables longer than a single character (i.e. all variables that you're likely to define) needs to be expanded with ${varname}, not $varname. The latter would result in the value of $v concatenated with the string arname, as you discovered.
I won't start to parse the rest of that Makefile as the piping looks a bit questionable.

store command output in variable

I am working on a script that executes ssh to few systems (listed in lab.txt), run two commands, store the output of commands in two different variables and print them.
Here is the script used :
#!/bin/bash
while read host; do
ssh -n root#$host "$(STATUS=$(awk 'NR==1{print $1}' /etc/*release) \
OS=$(/opt/agent/bin/agent.sh status | awk 'NR==1{print $3 $4}'))"
echo $STATUS
echo $OS
done < lab.txt
The lab.txt file contains few Ips where I need to login, execute and print the command output.
~#] cat lab.txt
192.168.1.1
192.168.1.2
While executing the script, the ssh login prompt of 192.168.1.1 is shown and after entering the password, the output is shown blank. Same as for next ip 192.168.1.2
When I execute these command manually within 192.168.1.1, the following is returned.
~]# awk 'NR==1{print $1}' /etc/*release
CentOS
~]# /opt/agent/bin/agent.sh status | awk 'NR==1{print $3 $4}'
isrunning
What could be wrong with the script? Is there a better way of doing this?
As the comment says, you are setting the variables inside the bash session on the server side and trying to read them from the client side.
If you want to assign the variables in the client script you need to put the assignment in front of the ssh command, and separate the two assignments. Something like the following.
STATUS=`ssh -n root#$host 'awk \'NR==1{print $1}\' /etc/*release)`
OS=`ssh -n root#$host '/opt/agent/bin/agent.sh status | awk \'NR==1{print $3 $4}\''`
You need to do two ssh commands. It also simplifies things if you run awk on the client rather than the server, because quoting in the ssh command gets complicated.
while read host; do
STATUS=$(ssh -n root#$host 'cat /etc/*release' | awk 'NR==1{print $1}')
OS=$(ssh -n root#$host /opt/agent/bin/agent.sh status | awk 'NR==1{print $3 $4}')
echo $STATUS
echo $OS
done < lab.txt
with one ssh statement:
read STATUS OS < <(ssh -n root#$host "echo \
\$(awk 'NR==1{print \$1}' /etc/*release) \
\$(/opt/agent/bin/agent.sh status | awk 'NR==1{print \$3 \$4}')")
echo $STATUS
echo $OS
Explanation:
The <(command) syntax is called process substitution. You can use it anywhere where a file is expected.
Example:
sdiff <(echo -e "1\n2\n3") <(echo -e "1\n3")
The command sdiff expects two files as arguments. With the process substitution syntax you can use commands as arguments. ( e.g. fake files )

Find and replace in shell script

I'm trying to replace the IP with New Ip but i'm not able to do so
Network_settings="1.1.1.1:8.9.0.0:9.9.9.9: IP ADDRESS: SUBNET MASK: GATEWAY"
val=`echo "$Network_settings"| cut -d ":" -f1`;
sed -ri 's/(\b[0-9]{1,3}\.){3}[0-9]{1,3}/ 'echo "$val"'/g' Network_settings.txt
val=$( echo "$Network_settings" | awk -F: 'BEGIN{OFS=":"}{$1="2.2.2.2"; print $0}')
This sets the new ip to 2.2.2.2
This uses awk.
The shell is not going to execute the echo command in this line:
sed -ri 's/(\b[0-9]{1,3}\.){3}[0-9]{1,3}/ 'echo "$val"'/g' Network_settings.txt
One way to do it is to use double-quotes for the sed script:
sed -ri "s/(\b[0-9]{1,3}\.){3}[0-9]{1,3}/$val/g" Network_settings.txt
Here's an example using sed:
sed -r 's/\b([0-9]{1,3}\.){3}[0-9]{1,3}\b/'$val'/'

Resources