Extracting text between two strings. These strings have spaces and are saved in variables

Viewed 104

I need to extract all the texts between the dates in the following manner (The format for the below is: Month Day Hour):

start_marker: "Jul  3 2" 
end_marker: "Jul  3 7"

from a log file that has data in the following example format

<unneeded text>
Fri Jul  3 2:51:54:780 2020
<needed text> 
<needed text> 
<needed text> 
Fri Jul  3 5:51:54:780 2020 
<needed text> 
<needed text> 
Fri Jul  3 7:51:54:780 2020 
<unneeded text>

I am trying the below script but it returns a blank log_collector file

start_month="Jul"
start_date="3"
start_hour="2"

end_month="Jul"
end_date="3"
end_hour="7"

start_marker="$start_month  $start_date $start_hour"
end_marker="$end_month  $end_date $end_hour"

sed -n '/"$start_marker"/,/"$end_marker"/p' logfile >> "log_collector"

cat log_collector
2 Answers

Use double quotes when using sed + variables otherwise sed wont read your variables, your script is now readed/executed as the file has been written in your example:

+ start_month=Jul
+ start_date=3
+ start_hour=2
+ end_month=Jul
+ end_date=3
+ end_hour=7
+ start_marker='Jul  3 2'
+ end_marker='Jul  3 7'
+ sed -n '/"$start_marker"/,/"$end_marker"/p' logfile 
+ cat log_collector
...empty file

Instead try:

sed -n "/${start_marker}/,/${end_marker}/p" logfile >> "log_collector"

Result:

+ variables...
+ sed -n '/Jul  3 2/,/Jul  3 7/p' logfile
+ cat log_collector
Fri Jul  3 2:51:54:780 2020
text...

And your script will now output the variables as you want.

But I really don't see the point with using start_* and end_* variables when you using *_marker for the same values, but maybe it was just an bad/confusing example :)

Hint: Launch your script with 'bash -x' or add 'set -x' and you will see how script is launched.

Edit: Bill Jetzer was faster I see in your comments, however see examples above.

FWIW I'd use a flag (inRange below) instead of a range (which excludes sed since it doesn't have variables) and only check for the date/time markers on lines that look like your date/time lines (hence the long-ish regexp below):

$ cat tst.awk
BEGIN { FS = "[[:space:]:]+" }
/^([[:upper:]][[:lower:]]{2} +){2}[0-9]{1,2} +([0-9]{1,2}:){3}[0-9]{3} +[0-9]{4} *$/ {
    marker = $2" "$3" "$4
}
marker == start_marker { inRange = 1 }
inRange { print }
marker == end_marker { inRange = 0 }

.

$ awk -v start_marker='Jul 3 2' -v end_marker='Jul 3 7' -f tst.awk file
Fri Jul  3 2:51:54:780 2020
<needed text>
<needed text>
<needed text>
Fri Jul  3 5:51:54:780 2020
<needed text>
<needed text>
Fri Jul  3 7:51:54:780 2020

See Is a /start/,/end/ range expression ever useful in awk? for why I wouldn't use a range expression (/start/,/end/).

Related