Hi I'm trying to print the 5 lines after a regular expression has been found using the awk command. I have the following:
line_start=$(awk '/regex/{print NR}' file)
let line_end=$line_start+4
awk 'NR==$line_start, NR==$line_end' file
This does not print anything. It doesnt hang, just goes on the next line.
I researched some similar problems, and saw people use the -v option. Am I supposed to use that here, their situations were for larger awk scripts.
By the way, I am using Kornshell
Thanks!
Variables are used to store any value temporary in any programming language. Defining the variable in awk command is similar to bash scripting language and it works like bash when the shell variable is used with a single quote and double quote. Awk command has many built-in variables for various purposes.
NR: NR command keeps a current count of the number of input records. Remember that records are usually lines. Awk command performs the pattern/action statements once for each record in a file. NF: NF command keeps a count of the number of fields within the current input record.
awk '{print $1}' information. txt prints the first column. Then the output of that command (which you saw earlier on) is piped, using the pipe symbol | , to the head command, where its -1 argument selects the first line of the column. If you wanted two lines printed, you'd do: awk '{print $1}' information.txt | head -2.
There are several problems with your script. The immediate problem is that in the second call to awk, you use single quotes around the script, so $line_start
and $line_end
are variables expanded by the shell, they're passed literally as part of the script to awk. You can fix this by using double quotes instead.
awk "NR==$line_start, NR==$line_end" file
This works only because $line_start
and $line_end
are numbers. If they were strings, you couldn't do this, because the values of the shell variables end up being parsed by awk as part of awk code, not as strings. In general, to pass a string to an awk script, you can use the idiom with -v
to define awk variables with the same name as the shell variables (or with different names if you prefer):
awk -v "line_start=$line_start" -v "line_end=$line_end" 'NR==line_start, NR==line_end' file
There are more problems with your script.
/regex/
, then $line_start
will contain a list of line numbers. The shell will complain of a syntax error on the let
line.If you want to show 5 lines following a match, do the counting inside awk.
awk '
/regex/ { show_lines = 5 }
show_lines { print; --show_lines; }
' file
If you only want to show the first matching block, exit once show_lines
reaches 0.
show_lines { print; --show_lines; if (!show_lines) exit; }
You can use sed for this:
sed -n '/regex/{N;N;N;N;N;p}' file
Or change the awk solution:
line_start=$(awk '/regex/{print NR}' file)
let line_end=$line_start+4
awk "{ if (NR>=$line_start && NR<=$line_end) print; }" file
Another awk solution (s.awk)
:
BEGIN { v = -1}
/regex/ { v = 0 }
v > -1 { v++ }
v > -1 && v < 5 { print }
v == 5 { exit }
use:
awk -f s.awk file
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With