How to perform multiple operations on a number before storing to a variable?

(I am using bash)
I have a command that will find the line number in a file by searching for a string where it exists.

linenumber=$(grep -n "string" $FILENAME | cut -d : -fi)

This returns the line number and removes the string. Now that I have the line number I want to subtract 4 from it and give me a new line number.

newlinenumber=$((linenumber - 4))

What I would like to do is find the line number and subtract by 4 BEFORE storing to the variable "linenumber" so I can avoid creating a new variable "newlinenumber" altogether. Essentially I want to combine the two with the idea pictured as follows:

linenumber=$(grep -n "string" $FILENAME | cut -d : -fi) | $((linenumber - 4)) 

I want to know the correct syntax to make this possible.

linenumber=$(expr $(grep -n "string" $FILENAME | cut -d : -f1) - 4)
1 Like
linenumber=$(( $(grep -n "string" $FILENAME | cut -d : -f1) - 4 ))
1 Like

How about LN=$(awk '/string/ {print NR - 4}' $FILENAME )?

1 Like

Thank you guys you are amazing. I went with RudiC's suggestion although all of them worked.

Note that you can assign a new value to a variable that has already been set without creating another variable name. Instead of

linenumber=$(grep -n "string" $FILENAME | cut -d : -fi)
newlinenumber=$((linenumber - 4))

(and assuming that the cut -fi was a typo and you meant

cut -f1[/ICODE)], you could use:
linenumber=$(grep -n "string" $FILENAME | cut -d : -f1)
linenumber=$((linenumber - 4))

and, you can get rid of the cut completely with: linenumber=$(grep -n "string" $FILENAME)) linenumber=${linenumber%%:*} linenumber=$((linenumber - 4)) which also keeps you from getting a syntax error if more than one line in your file contains "string" (in which case this will set linenumber to the number of the 1st line in the file containing "string" minus four). And, this could also be written as:

linenumber=$(grep -n "string" $FILENAME))
linenumber=$((${linenumber%%:*} - 4))

or:

linenumber=$(awk '/string/ {print NR - 4; exit}' $FILENAME )

or, if there is a chance that "string" won't appear in the file at all:

linenumber=$(awk '/string/ {print NR - 4; f=1; exit} END {if(!f) print -1}' $FILENAME )

(where the print -4 in the END section matches what the above bash code does if there are no matches).