What do back brackets do in this bash script code? - linux

so i'm doing a problem with bashscript, this one: ./namefreq.sh ANA should return a list of two names (on separate lines) ANA and RENEE, both of which have frequency 0.120.
Basically I have a file from table.csv shown in the code below that have names and a frequency number next to them e.g. Anna, 0.120
I'm still unsure what the `` does for this code, and I'm also struggling to understand how this code is able to print out two names with identical frequencies. The way I read the code is:
grep compares the word (-w) typed by the user (./bashscript.sh Anna) to the value of (a), which then uses the cut command to be able to compare the 2nd field of the line separated by the delimiter "," which is the frequency from the file table.csv and then | cut -f1 -d"," prints out the first fields which are the names with the same frequency
^ would this be correct?
thanks :)
#!/bin/bash
a=`grep -w $1 table.csv | cut -f2 -d','`
grep -w $a table.csv | cut -f1 -d',' | sort -d

When a command is in backticks or $(), the output of the command is subsituted back into the command in place of it. So if the file has Anna,0.120
a=`grep -w Anna table.csv | cut -f2 -d','`
will execute the grep and cut commands, which will output 0.120, so it will be equivalent to
a=0.120
Then the command looks for all the lines that match 0.120, extracts the first field with cut, and sorts them.

Related

How to find a substring from some text in a file and store it in a bash variable?

I have a file named config.txt which has following data:
ABC_PATH=xxx/xxx
IMAGE=docker.name.net:3000/apache:1.8.109.1
NAMESPACE=xxx
Now I am running a shell script in which I want to store 1.8.109.1 (this value may differ, rest will remain same) in a variable, maybe using sed, awk or any other linux tool.
How can I achieve that?
The following will work.
ver="$(cat config.txt | grep apache: | cut -d: -f3)"
grep apache: will find the line that has the text 'apache:' in it.
-d specifies what delimiters to use. In this case : is set as the delimiter.
-f is used to select the specific field (array index, starting at 1) of the resulting list obtained after delimiting by :
Thus, -f3 selects the 3rd occurence of the delimited list.
The version info is now captured in the variable $ver
I think this should work:
cat config.txt | grep apache: | cut -d: -f3

How to get the lines from a list of IP addresses which has the fourth octet more than 10?

I have the following output:
netman#netman:~/Desktop$ nmap -p 80,443,8080 --open 172.20.74.0/24 | grep report | cut -d"(" -f2 | cut -d")" -f1 | sed '/172.20.74.(0-9)/d'
172.20.74.4
172.20.74.11
172.20.74.40
172.20.74.212
I need a way ( sed or awk or any other command) to get the IP addresses in the range 172.20.74.11 - 172.20.74.255
I tried Sed and another commands like grep, but to no avail.
Thanks in advance
. . . | awk '-F.' '$4>10'
produces output
172.20.74.11
172.20.74.40
172.20.74.212
from the 4 IPs you included above. Did I understand your need correctly?
This approach relies on awks ability to operate on numbered fields based on specifing an alternate value for FS (Field Separator). I have used the command-line option '-F.' to set FS.
Because you want the 4th field, we only need compare $4>10. Only lines that match that comparison are printed.
A long hand version would be
. . . | awk 'BEGIN{FS="."}{if ($4 > 10) print $0}'
where $0 refers to the whole line of input and $4 refers to the 4th field in the line, when using the '.' as the Field Separator and the default action is to process (test) all lines of input (in this example, coming from your pipeline).
IHTH

Sed, Awk for combining the output of two cut statements

I'm trying to combine the below outputs into one command. The issue is that the field I'm trying to grab is in reverse order. I was told that cut doesn't support a "reverse" option and to use AWK for this purpose but it didn't end up working for my purpose. I'm trying to take the output of the ls- l against the /dev/block to return the partitions and automatically build a dd if= / of= for each outputted line based on the output of the command.
I tried piping the output to awk:
cut -d' ' -f23,25 ... | awk '{print $2,$1}'
however, the result was when using sed to input the prefix and suffix, it wasn't in the appropriate order.
I built the two statements below which individually return the expected output, just looking for the "right" way to combine both of these statements in the most efficient manner using sed / awk.
ls -l /dev/block/platform/msm_sdcc.1/by-name/ | cut -d' ' -f 25 | sed "s/^/dd if=/"
ls -l /dev/block/platform/msm_sdcc.1/by-name/ | cut -d' ' -f 23 | sed "s/.*/of=\/external_sd\/&.dsk/"
Any assistance will be appreciated.
Thank you.
If you're already using awk, I don't think you'll need cut or sed. You can probably do something like the following, though I'll have to trust you on the field numbers
ls -l /dev/block/platform/msm_sdcc.1/by-name | awk '{print "dd if=/"$25 " of=/" $23 ".dsk"}'
awk will split on all whitespace, not just the space character, so it's possible the fields will shift some, though it may be more reliable too.

Cut and Awk command : Delimiter behaviour

I tried to use cut command to get a list of file names and their sizes from "ls -l" command output.
$ ls -l | cut -f 5,9 -d " "
It gives me output based on 'SINGLE WHITE SPACE' as a delimiter. When "ls -l" output contains consecutive spaces in certain rows, then the output of the command is not proper for those rows.
The rows which have only single white space as column separator, give correct output.
When I run following command:
$ ls -l | awk '{ print $5"\t"$9 }'
awk is ignoring multiple spaces and properly extracting columns from "ls -l" output.
While, cut is treating each space as a delimiter, there by putting values in wrong columns.
It gives correct output for all rows.
Why is this happening ? What can I do to work this out with cut command ?
awk splits fields on whitespace. cut splits fields on a delimiting character. awk is the better tool for this problem.
As an alternative, you can pipe ls -l into a utility that either compresses multiple space chars (maybe tr -s), or into a utility that replaces multiple space chars with a single one (maybe sed). Then cut will do what you want it to.
Don't parse ls -- your code will not print the full filename if it contains spaces. To get the file size and name, use stat:
stat -c "%s %n" *
try this?:
ls -l | tr -s ' ' | cut -d ' ' -f 5, 9

Unix cut except last two tokens

I'm trying to parse file names in specific directory. Filenames are of format:
token1_token2_token3_token(N-1)_token(N).sh
I need to cut the tokens using delimiter '_', and need to take string except the last two tokens. In above examlpe output should be token1_token2_token3.
The number of tokens is not fixed. I've tried to do it with -f#- option of cut command, but did not find any solution. Any ideas?
With cut:
$ echo t1_t2_t3_tn1_tn2.sh | rev | cut -d_ -f3- | rev
t1_t2_t3
rev reverses each line.
The 3- in -f3- means from the 3rd field to the end of the line (which is the beginning of the line through the third-to-last field in the unreversed text).
You may use POSIX defined parameter substitution:
$ name="t1_t2_t3_tn1_tn2.sh"
$ name=${name%_*_*}
$ echo $name
t1_t2_t3
It can not be done with cut, However, you can use sed
sed -r 's/(_[^_]+){2}$//g'
Just a different way to write ysth's answer :
echo "t1_t2_t3_tn1_tn2.sh" |rev| cut -d"_" -f1,2 --complement | rev

Resources