LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Using a variable in sed to pick a specific line from a text file, bash (https://www.linuxquestions.org/questions/linux-newbie-8/using-a-variable-in-sed-to-pick-a-specific-line-from-a-text-file-bash-4175421679/)

Sunvic 08-12-2012 05:36 AM

Using a variable in sed to pick a specific line from a text file, bash
 
I'm trying to run the command iwlist scan, remove the errors and process the output to my own specification by using grep & sed to find and pick specific lines, from a text file, over a for loop and then store some of the information as a variable for future use as I develop the code

my code looks like this at the moment

Code:

#!/bin/bash

# counts number of cells found, i.e. number of broacasting routers in range
varA=`iwlist scan 2>/dev/null | egrep  -c "Cell"`

#saves the output minus errors
iwlist scan 2>/dev/null | egrep  "Address" > ~/Desktop/coutput1

# my for loop where i try to set var(1,2,3 etc) to the output in coutput1
for i in $(eval echo {1..$varA})
do
var$i=`sed -n "$i"p "~/Desktop/coutput1" | cut -c 30-47`
done

# print var's
echo $varA
echo $var$1

I try to cut the output below and for example save var1 as the address for cell 01

where coutput1 looks like this:
Code:

          Cell 01 - Address: AA:BB:CC:DD:EE:FF
          Cell 02 - Address: AA:BB:CC:DD:EE:FF
          Cell 03 - Address: AA:BB:CC:DD:EE:FF

the line
Code:

var$i=`sed -n "$i"p "~/Desktop/coutput1" | cut -c 30-47`
just doesn't seem to want to work and i don't know where to go. Maybe there's other problems with the rest of the code?

I appreciate that this code is inefficient but most of it was for my own learning and compiled from multiple online guides etc

pixellany 08-12-2012 06:07 AM

If I read it correctly, you want to print only the lines containing the contents of the variable "i".

For that, write the SED command like this:

sed -n "/$i/p" filename

The double-quotes allow the variable name to be expanded before sed processes it.


The address range in SED is either by line number, or by content. If you use line numbers, then the /../ is not used.

Sunvic 08-12-2012 06:24 AM

Thanks for your quick and helpful reply.

I changed the code slightly to build an array and using your /../ I altered the line to read:

Code:

var[$i]=`sed -n /$i/p ~/Desktop/coutput1 | cut -c 30-47`
which now cuts the address out precisely and stores it as the specific var

grail 08-12-2012 06:30 AM

The issue with the line is the use of variable expansion on the left side of the equals.
I would also query the need to use eval?? Is there a reason you do not create a simple for loop?

My suggestion for the "var" variable would be to make it an array

Sunvic 08-12-2012 06:35 AM

*thinking I had created a simple for loop*

My only knowledge really comes from Matlab, how would you suggest the for loop is created to incorporate the maximum being the variable varA?

instead of storing as an array (which is like a row vector?) can I create a 2D-matrix (to store more information as I increase the variables, I would like to store SSID's and channels etc)?

thanks for your help

pixellany 08-12-2012 07:55 AM

You can sometimes get away with it, but it is recommended practice to always quote the sed command string. The typical recommendation is to use hard quotes (single), unless, there is a need for soft quotes (eg your case).

Also, the use of backtics (while still legal) is "deprecated".

Incorporating these 2 comments, the form would be:
Code:

variable=$(sed -n "/$i/p" ~/Desktop/coutput1 | cut -c 30-47)

Sunvic 08-12-2012 08:30 AM

Thanks for the continued help

Code:

#!/bin/bash
clear

#save the output minus errors
iwlist scan 2>/dev/null | egrep  "Address" > ~/Desktop/coutput1

# counts number of cells found, i.e. number of broacasting routers in range
varA=`egrep  -c "Cell" ~/Desktop/coutput1`
echo $varA

# for loop to assign array var to each address
for ((i=1; i<=$varA; i++));
do
echo $i
var[$i-1]=$(sed -n -e "/$i/p" ~/Desktop/coutput1 | cut -c 30-46)
done

echo ${var[@]}

Is my new code (including a change in the way the for loop is built) but it returns something confusing.
I have var starting at 0 as I have read this is the first entry?
But on the last echo command I get more entries than varA implies I should be getting. ie if there's 3 addresses var seems to have these 3 addressed stored multiple times and in strange orders.

Here's an example if I run the script of the output of echo var:
Code:

2C:B0:5D:CC:98:26 00:01:E3:E8:D6:88 2C:B0:5D:CC:98:26 00:22:3F:32:9C:52 00:22:3F:32:9C:52 00:01:E3:E8:D6:88
when I thought it should only return 3 addresses for this case?

grail 08-12-2012 08:50 AM

I was wondering if you could show the output of your 'iwlist scan' as this seems to be a bit excessive (number of steps and some redundancy of repeated tasks, ie sed and grep)?

In answer to your question, have a think about what you have asked of sed? ie. On the first run when i = 1, you tell sed to find and print all lines that contain a '1'.
So if you extrapolate this into what would be presented each time (btw this is a simple grep when you look at it), you can see that there may be more lines with a 1, 2 or 3 on them so multiple returns.

Sunvic 08-12-2012 09:08 AM

Oh I see what you mean about the command i've given sed and it makes perfect sense, clearly I was under the impression that using -n -e searched for the specific line number given and this is not true.

altered the line to read:
Code:

var[$i]=$(awk "NR==$i" ~/Desktop/coutput1 | cut -c 30-46)
which seems to have sorted out my problem.

Thanks for your help

pixellany 08-12-2012 10:21 AM

-n means do not print by default
-e means use extended regexes

SED tutorial here:
http://www.grymoire.com/Unix/Sed.html

grail 08-12-2012 11:03 AM

The sed would work just as well:
Code:

sed -n "$i p" ~/Desktop/coutput1


All times are GMT -5. The time now is 02:53 PM.