Assign bash value from value in specific line - bash

I have a file that looks like:
>ref_frame=1
TPGIRYQYNVLPQGWKGSPAIFQSSMTKILEPFRKQNPDIVIYQYMDDLYVGSD
>ref_frame=2
HQGLDISTMCFHRDGKDHQQYSKVA*QKS*SLLENKIQT*LSINTWMICM*DLT
>ref_frame=3
TRD*ISVQCASTGMERITSNIPK*HDKNLRAF*KTKSRHSYLSIHG*FVCRI*
>test_3_2960_3_frame=1
TPGIRYQYNVLPQGWKGSPAIFQSSMTKILEPSRKQNPDIVIYQYMDDLYVGSD
I want to assign a bash variable so that echo $variable gives test_3_2960
The line/row that I want to assign the variable to will always be line 7. How can I accomplish this using bash?
so far I have:
variable=`cat file.txt | awk 'NR==7'`
echo $variable = >test_3_2960_3_frame=1

Using sed
$ variable=$(sed -En '7s/>(([^_]*_){2}[0-9]+).*/\1/p' input_file)
$ echo "$variable"
test_3_2960

No pipes needed here...
$: variable=$(awk -F'[>_]' 'NR==7{ OFS="_"; print $2, $3, $4; exit; }' file)
$: echo $variable
test_3_2960
-F is using either > or _ as field separators, so your data starts in field 2.
OFS="_" sets the Output Field Separator, but you could also just use "_" instead of commas.
exit keeps it from wasting time bothering to read beyond line 7.

If you wish to continue with awk
$ variable=$(awk 'NR==7' file.txt | awk -F "[>_]" '{print $2"_"$3"_"$4}')
$ echo $variable
test_3_2960

Related

How to print from the first period to the second period using awk?

20200601.title.info.event.txt is the file name. I want to use awk to print whatever is in between the first two periods. So in this case "title." Appreciate any help.
The file is a $1 variable. All files are formatted with the same info.
I'm using
FILE=$1
DATE=echo $FILE | awk '{printf "%", substr ($1,1,8)' -
TITLE=
Need to grab the TITLE in between the the first two periods to use as a variable elsewhere. The TITLE will be different for every file. Thank you all for the help.
Like this:
cut -d'.' -f2 <<< 20200601.title.info.event.txt
This is the straightforward way to cut a string.
And with awk like #Mihir wrote in comments:
awk -F. '{print $2}' <<< 20200601.title.info.event.txt
Using awk's split() instead of FS in case it's used for something else::
$ awk '
BEGIN {
split("20200601.title.info.event.txt",a,".")
print a[1]
}'
title
Using bash's =~ operator:
$ [[ "20200601.title.info.event.txt" =~ \.[^.]*\. ]] && echo ${BASH_REMATCH[0]:1:-1}
title
Using sed:
$ sed 's/^[^.]*.\|\..*//g' <<< "20200601.title.info.event.txt"
title
In all cases you could set the string to a variable first and use the variable instead of the string.

How to print the result of a system command in awk

I have the following single line in my bash script:
echo "foo" | awk -F"=" '{char=system("echo $1 | cut -c1");}{print "this is the result: "$char;}' >> output.txt
I want to print the first letter of "foo" using awk, such that I would get:
this is the result: f
in my output file, but instead, I get:
this is the result: foo
What am i doing wrong?
Thanks
No, this is not the way system command works inside awk.
What's happening in OP's code:
You are giving a shell command in system which is good(for some cases) but there is a problem in this one that you should give it like system("echo " $0" | cut -c1") to get its first character AND you need NOT to have a variable etc to save its value and print it in awk.
You are trying to save its result to a variable but it will not have its value(system command's value) but its status. It doesn't work like shell style in awk in here.
So your variable named char will have 0 value(which is a success status from system command) and when you are printing $char it is printing whole line(because in awk: print $0 means print whole line).
You could do this in a single awk by doing:
echo "foo" | awk '{print substr($0,1,1)}'
OR with GNU awk specifically:
echo "foo" | awk 'BEGIN{FS=""} {print $1}'
you're not using much of awk, same can be done with printf
$ echo "foo" | xargs printf "this is the result: %.1s\n"
this is the result: f
or, directly
$ printf "this is the result: %.1s\n" foo
this is the result: f

Passing two awk columns into a while read command

SampleFile:
Two Words,Extra
My code:
cat SampleFile | awk -F "," '{print $1" "$2}' | while read var1 var2;
do
echo $var1
done
This will print out only Two and var2 will take Words. Is there a way so that I can pass Two Words into var1?
You don't have to use awk for this. Bash has a built-in variable to determine where words are split:
while IFS=, read -r var1 var2; do
echo "$var1"
done < SampleFile
IFS is set to ,, so word splitting takes place at commas.
Instead of piping to the while loop, I use redirection, which has the advantage of not spawning a subshell.
A remark: you don't need cat in this context. Awk can take a file name as an argument, so
cat SampleFile | awk -F "," '{print $1" "$2}'
becomes
awk -F "," '{print $1, $2}' SampleFile
Also, when using print, you don't need to explicitly introduce spaces: if you comma-separate your fields, awk will replace the comma by the value of the OFS (output field separator) variable, which defaults to a space.
...| while read var1; do echo $var1 done

extracting a variable's value from text file using bash

I am using Linux and bash.
I have a simple text file like below:
VAR1=100
VAR2=5
VAR3=0
VAR4=99
I want to extract by means of bash the value of VAR2, that is 5.
How could I do that?
Assuming the file is called vars.txt
sed -n 's/^VAR2=\(.*\)/\1/p' < vars.txt
You can use the value elsewhere like this using single back quotes
echo VAR2=`sed -n 's/^VAR2=\(.*\)/\1/p' < txt`
The simplest way might be to use source or simply . to read and execute the file. This would work with your example, because there are no spaces in the variable values. Otherwise you need to use grep + cut or awk, as stated in other answers.
. /path/to/your/file
echo $VAR2
[edit]
As stated by dawg, this would make the other variables available in your script too, and possibly overwrite existing variables.
Given:
$ echo "$txt"
VAR1=100
VAR2=5
VAR3=0
VAR4=99
You can use awk:
$ echo "$txt" | awk -F= '/^VAR2/ { print $2 }'
5
Or grep and cut:
$ echo "$txt" | egrep '^VAR2=\d+' | cut -d = -f 2
5
On Bash, you can insert the value of those assignments into the current shell using source and filter the lines you wish to use. In this case, only the line VAR2=5 will be used. You need to write that to a file and then source that file:
$ echo "$txt" | grep '^VAR2' > tmp && source tmp && rm tmp
$ echo $VAR2
5
For the files as described, you can just source the file as bash script which will run it's content and update you workspace environment with it. For example:
source file.txt
echo $VAR2
Assume this as your txt file, named test.txt
VAR2 = 5
VAR3 = 0
VAR4 = 99
you can cat test.txt | grep 'VAR2' | awk '{printf $3}'
and then your output will be: 5
Here, cat test.txt will display the content of test.txt in your terminal,grep 'VAR2' will list lines containing 'VAR2' and awk '{printf $3}' will print the value of the variable

How to assign the output of a command to a variable?

this is probably a very stupid question; in a bash script, given the output of, for instance;
awk '{print $7}' temp
it gives 0.54546
I would like to give this to a variable, so I tried:
read ENE <<< $(awk '{print $7}' temp)
but I get
Syntax error: redirection unexpected
Could you tell me why, and what is the easiest way to do this assignment?
Thanks
You can do command substitution as:
ENE=$(awk '{print $7}' temp)
or
ENE=`awk '{print $7}' temp`
This will assign the value 0.54546 to the variable ENE
your syntax should be
read ENE <<<$(awk '{print $1}' file)
you can directly assign the value as well
ENE=$(awk '{print $7}' temp)
you can also use the shell
$ var=$(< temp)
$ set -- $var
$ echo $7
or you can read it into array
$ declare -a array
$ read -a array <<<$(<file)
$ echo ${array[6]}
In general, Bash is kinda sensitive to spaces (requiring them some places, and breaking if they are added to other places,) which in my opinion is too bad. Just remember that there should be no space on either side of an equal sign, there should be no space after a dollar sign, and parentheses should be lined with spaces ( like this ) (not like this.)
`command` and $( command ) are the same thing, but $( this version can be $( nested ) ) whereas "this version can be `embedded in strings.` "

Resources