Home > Enterprise >  Get contents between two locations in a text file using bash
Get contents between two locations in a text file using bash

Time:07-19

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 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..
  •  Tags:  
  • bash
  • Related