I am trying to get the contents between two locations in a text file. The text file varies in the number of lines between this two location.
example
Location1:
more lines..
mores lines.
more lines..
Location2
These two locations can appear at the beginning of the text file or in the middle.
I have managed to get to Location1 using
cat filename | grep -A 10 Location1
However the number of lines between the two locations is not fixed to 10.
CodePudding user response:
Not sure if you need one bash command or a script, but you can achieve the goal using following code:
#!/usr/bin/bash
FILENAME=$1
LINE_1=$2
LINE_2=$3
idx_1=$(awk "/$LINE_1/{ print NR; exit }" $FILENAME)
idx_2=$(awk "/$LINE_2/{ print NR; exit }" $FILENAME)
# Debug
echo "$LINE_1 idx: $idx_1"
echo "$LINE_2 idx: $idx_2"
cat $FILENAME | awk "{if (NR > $idx_1 && NR < $idx_2) print \$0}"
Test file:
more lines...
Location1
more lines..
mores lines.
more lines..
Location2
more lines...
more lines..
Launch example:
./get_content_between_lines.sh sample.txt Location1 Location2
Location1 idx: 2
Location2 idx: 6
more lines..
mores lines.
more lines..
CodePudding user response:
pure bash solution
#!/bin/bash
filename=$1;
# find the line numbers of matches
mapfile -t index < <(grep -hn -e Location1 -e Location2 $filename | grep -o '^[[:digit:]]\ ');
# subtract them to get the offset
declare -i grep_offset=$((index[1] - index[0]));
# no need to use ${} inside ((...)) operator
# declare -i grep_offset=$((${index[1]} - ${index[0]}));
# decrease by one, to ignore second match
let --grep_offset
# match from first one up to $grep_offset , then tail it ignoring first match
grep -A $grep_offset Location1 $filename | tail -n $grep_offset
input
something above
something above
something above
something above
Location1
more lines..
more lines..
mores lines.
mores lines.
more lines..
more lines..
Location2
something below
something below
something below
something below
output
more lines..
more lines..
mores lines.
mores lines.
more lines..
more lines..
Perl one-liner including the matches:
perl -lne '$/=unset; /Location1.*Location2/gs && print $&' file.txt
Location1
more lines..
more lines..
mores lines.
mores lines.
more lines..
more lines..
Location2
Perl one-liner excluding the matches
perl -ne '$/=unset; /(?<=Location1\n).*(?=Location2)/gs && print $&' file.txt
more lines..
more lines..
mores lines.
mores lines.
more lines..
more lines..