0

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.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Jason Aruni
  • 23
  • 1
  • 5
  • `sed -n '/Location1/,/Location2/p' filename` or `awk '/Location1/,/Location2/' filename` – Shawn Jul 17 '22 at 18:57
  • if you know with *100% certainty* that a) each 'start' has a matching 'end' and b) the strings that make up the 'start/end' do not show up anywhere else in the file, a couple ideas: `sed -n '/Location1/,/Location2/p'` or `awk '/Location1/,/Location2/'`; keep in mind these are very simplistic answers that break quite easily if you cannot guarantee with *100% certainty* the two prerequisites I've mentioned – markp-fuso Jul 17 '22 at 18:58
  • Can there be two-digit numbers in the file after the string `Location` (e.g. `Location10`)? – Cyrus Jul 17 '22 at 19:02
  • Take a look: [How to print lines between two patterns, inclusive or exclusive (in sed, AWK or Perl)?](https://stackoverflow.com/q/38972736/3776858) – Cyrus Jul 17 '22 at 19:04

3 Answers3

0

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..
Stanislav
  • 23
  • 7
0

pure 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..
Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
0
$ awk '/Location1/{f=1; next} /Location2/{f=0} f{print}' file
more lines..
mores lines.
more lines..
ufopilot
  • 3,269
  • 2
  • 10
  • 12