sed searching across lines

hi,

i'm making now a bash script, that runs some compiler... i want to take only errors form its output eg:

output:

bla bla bla
...
erros is 1324546
the bla bla bla 

bla bla bla...
...

and i want to get only

erros is 1324546
the bla bla bla 

i've managed to do something like this:

cat errors_file | sed -n "N;s/errors.*\n/&/P"

but i don't know how to do something like (.*\n)* how can this be done?

Try this:

sed -n '/erros is/{N;p;}' errors_file

Jean-Pierre.

this is not exactly what i want... becouse i don't know how many lines error will have... all i know it beigns with:"errors is" and ends with ^$

#edited

and can you explain what your command does? as i understand it it will print out the maching line and the one follwing it... but why this strange syntax? why do you do some {} at the end? where is s/?

In that case :

sed -n '/erros is/,/^$/p' errors_file

/error is/{ ... }
Select lines that contains 'erros is' and execute commands '...'
N;p
Append next line to current line and print the whole

Jean-Pierre.

cooooooooool :slight_smile: this is great :slight_smile: can you explain me this command?

btw. big, big biiiiiiiiig thanks :smiley:

From sed man page :

/erros is/,/^$/p
First line contains 'erros is' and last line is empty.

Jean-Pierre.

ok, but what is this comma for? - stupid me... i didn't read the quote :o

#edited

and if i'd like to place # before each line that i find?

If you want to display lines from 'errors is' to empy line with '#' at the begening of each line :

sed -n '/erros is/,/^$/{s/^/#/;p;}' errors_file

To print whole file with error lines prefixed by '#'

sed '/erros is/,/^$/s/^/#/' errors_file

Jean-Pierre.

hi again,

what you've told was great - i'm really impressed :slight_smile: but... as it seems... i don't know exactly all the error messages (oracle), but i need to catch them all, and filter out the lines with no errors... so i've got two choices:

  1. filter out the messages without errors -> "No errors ......... ^$"
  2. catch all error messages - here starts the problem... i don't know all the error codes... besides i think that i can miss some, even then...

so my question is, how can i filter all lines begining with "No errors (bla bla bla) ^$" (ending with new line) + one line before it.... ofcourse i could write a C program and don't bother... but i'd like to write it all in shell... can somebody help me with this?

example oracle error (it's not strictly an error, but that doesn't matter):

FRM-30188: No initial value given, and other values are not allowed (item B_DATE.MONTH).
List MONTH
Block: B_DATE

and message with no errors:

Compiling PRE-TEXT-ITEM trigger in PC_DATE property class...
   No compilation errors.

ok, i've written a little c++ program to manage that... i anybody is interested here is the code:

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

int main( int argc, const char* argv[] )
{
	if (argc == 1)
	{
		cerr << "Please specify the input file." << endl;
		return 1;
	}

	ifstream file;
	file.open(argv[1]);

	if (!file.is_open())
	{
		cerr << "Couldn't open file: " << argv[1] << endl << "Terminating program." << endl;
		return 2;
	}

	std::string buf;
	std::string line;
	
	std::getline(file, line);//Compiler version info 

	cout << "# " << endl << "# " << line << endl;

	while (std::getline(file, line) && line.find("Oracle CORE") != 0){}//trimming the garbage
	
	cout << "# "  << endl;

	while(std::getline(file, line))
	{
		if (line.find("Compiling ") == 0)
		{
			std::getline(file, line);//No compilation errors.
			std::getline(file, line);//<blank line>
		}
		else
			cout << "# " << line << endl;;

	}

	cout << "# "  << endl;

	file.close();
	
	return 0;
}

don't really have to code in C in order to do that
Alternative in Python, which is much easier:
Input file sample:
bla bla
...
erros is 1324546
the bla bla bla

bla bla bla...
...
...
bla bla
erros is 32423423
the bla bla 1
the bla bla 2
the bla bla 3

bla bla

all = open("input.txt").readlines()
for number,items in enumerate(all):
        if "erros" in items:
                num = number
        if items == "\n":
                print ''.join(all[num:number])

Output:

[root@localhost test]# ./test.py
erros is 1324546
the bla bla bla

erros is 32423423
the bla bla 1
the bla bla 2
the bla bla 3

not quite... i have noiced, that some errors have also blank line "in" them, so i ended up writing a code that will find another "Compiling " string + added line breaking (based on words) so i can add '#' in front, and each bug is spaced with "-------------------" :smiley:

if anyone is interested:

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

void print_the_line(string s)//function for line breaking
{
	if (s.size() > 70)
	{
		string out = "", tmp = "";

		for (unsigned int i = 0; i < s.size(); i++)
		{
			tmp += s;

			if (s == ' ')
			{
				if (tmp.size() + out.size() < 70)
				{
					out += tmp;
					tmp = "";
				}
				else
				{
					cout << "# " << out << endl;			
					out = tmp;
					tmp = "";
				}
			}

		}

		cout << "# " << out << tmp << endl;
	}
	else
		cout << "# " << s << endl;
}

int main( int argc, const char* argv[] )
{
	if (argc == 1)
	{
		cerr << "Please specify the input file." << endl;
		return 1;
	}

	ifstream file;
	file.open(argv[1]);
	//file.open("error1.txt");

	if (!file.is_open())
	{
		cerr << "Couldn't open file: " << argv[1] << endl << "Terminating program." << endl;
		return 2;
	}

	std::string buf;
	std::string line;
	
	std::getline(file, line);//Compiler version info 

	print_the_line("");
	print_the_line(line);

	while (std::getline(file, line) && line.find("Oracle CORE") != 0){}//trimming the garbage
	
	print_the_line("");

	while(std::getline(file, line))
	{
		if (line.find("Compiling ") == 0)
		{
			std::getline(file, line);

			if ( line.find("No compilation errors") == string::npos )//not found - we must write the line 
			{														 //till we find another "Compiling "
				print_the_line("------------------------------------------------------------------");
				print_the_line(line);
			}
			else//we found string - everything is ok, so let's delete the blank line
			{
				std::getline(file, line);//<blank line>	
			}
		}
		else
			print_the_line(line);

	}

	print_the_line("");

	file.close();
	
	return 0;
}

but your solution is very interesting, i'm just too lame in bash to write a full script... so i eneded up mixing both...