Pete
Pete

Reputation: 101

How do I display data from the beginning of a file until the first occurrence of a regular expression?

How do I display data from the beginning of a file until the first occurrence of a regular expression?

For example, if I have a file that contains:

One
Two
Three
Bravo
Four 
Five

I want to start displaying the contents of the file starting at line 1 and stopping when I find the string "B*". So the output should look like this:

One
Two
Three

Upvotes: 8

Views: 5159

Answers (11)

Vijay
Vijay

Reputation: 67231

one liner with basic shell commands:

head -`grep -n B file|head -1|cut -f1 -d":"` file

Upvotes: 0

draegtun
draegtun

Reputation: 22560

sed -n '1,/^B/p'

Print from line 1 to /^B/ (inclusive). -n suppresses default echo.


Update: Opps.... didn't want "Bravo", so instead the reverse action is needed ;-)

sed -n '/^B/,$!p'  

/I3az/

Upvotes: 6

brian d foy
brian d foy

Reputation: 132822

Your problem is a variation on an answer in perlfaq6: How can I pull out lines between two patterns that are themselves on different lines?.


You can use Perl's somewhat exotic .. operator (documented in perlop):

perl -ne 'print if /START/ .. /END/' file1 file2 ...

If you wanted text and not lines, you would use

perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...

But if you want nested occurrences of START through END, you'll run up against the problem described in the question in this section on matching balanced text.

Here's another example of using ..:

while (<>) {
    $in_header =   1  .. /^$/;
    $in_body   = /^$/ .. eof;
# now choose between them
} continue {
    $. = 0 if eof;  # fix $.
}

Upvotes: 2

Pete
Pete

Reputation: 101

Just sharing some answers I've received:

Print data starting at the first line, and continue until we find a match to the regex, then stop:

<command> | perl -n -e 'print "$_" if 1 ... /<regex>/;'

Print data starting at the first line, and continue until we find a match to the regex, BUT don't display the line that matches the regular expression:

<command> | perl -pe '/<regex>/ && exit;'

Doing it in sed:

<command> | sed -n '1,/<regex>/p'

Upvotes: 2

Dennis Williamson
Dennis Williamson

Reputation: 360133

Some of the sed commands given by others will continue to unnecessarily process the input after the regex is found which could be quite slow for large input. This quits when the regex is found:

sed -n '/^Bravo/q;p'

Upvotes: 3

jmcnamara
jmcnamara

Reputation: 41584

Here is a perl one-liner:

perl -pe 'last if /B/' file

Upvotes: 1

rjh
rjh

Reputation: 50294

perl -pe 'last if /^B/' source.txt

An explanation: the -p switch adds a loop around the code, turning it into this:

while ( <> ) {
    last if /^B.*/;  # The bit we provide
    print;
}

The last keyword exits the surrounding loop immediately if the condition holds - in this case, /^B/, which indicates that the line begins with a B.

Upvotes: 11

ghostdog74
ghostdog74

Reputation: 342433

if its from the start of the file

awk '/^B/{exit}1' file

if you want to start from specific line number

awk '/^B/{exit}NR>=10' file # start from line 10

Upvotes: 7

user236875
user236875

Reputation:

If Perl is a possibilty, you could do something like this:

% perl -0ne 'if (/B.*/) { print $`; last }' INPUT_FILE

Upvotes: 0

ndim
ndim

Reputation: 37787

sed '/^B/,$d'

Read that as follows: Delete (d) all lines beginning with the first line that starts with a "B" (/^B/), up and until the last line ($).

Upvotes: 5

catwalk
catwalk

Reputation: 6476

in Perl:

perl -nle '/B.*/ && last; print; ' source.txt

Upvotes: 2

Related Questions