0

I've made a C program that implements printenv | grep [arguments] | sort | less, but for some reason I'm getting a bunch of newlines at the start of my output. Probably it's because of how I'm writing the environment variables from the parent process to the grep process. My results if I run myProgram PATH:

/*40 blank lines */
INFOPATH=/usr/share/info
MANPATH=/usr/local/vol/matlab/7.4.0/man:/usr/kerberos/man:/usr/local/share/man:/usr    /share/man/en:/usr/share/man:/usr/man
MODULEPATH=/usr/local/vol/modulefiles:/pkg/modules/modulefiles:/etc/site/modulefiles:    /usr/share/Modules/modulefiles:/etc/modulefiles
PATH=/usr/lib/heimdal/bin:/usr/local/vol/comsol/3.4/bin:/usr/local/vol/maple/10.05/bin:/usr/local/vol/matlab/7.4.0/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/opt/real/RealPlayer
WMMENUPATH=/usr/local/vol/maple/menudef/10.05:/usr/local/vol/fvwm2/menudefs/emacs:/usr/local/vol/fvwm2/menudefs/acroread

I'm using C to call and connect shell programs with pipes. Every program (grep, sort, less/more) is called in it's own child process and piped to the others. The parent process writes the environment variables to grep through a pipe like this:

for(i=0; envp[i]!=NULL; i++)
{
    return_value = write(pipe_fd[0][PIPE_WRITE],envp[i], strlen(envp[i]));
    errorCheck(return_value, "Cannot write to pipe in parent\n");
    return_value=write(pipe_fd[0][PIPE_WRITE],"\n",1);
    errorCheck(return_value, "Cannot write to pipe in parent\n");
}

I've tried adding a bunch of options to the sort call, but nothing has worked so far. My question is if there's a way to ignore multiple newlines in a row with either grep or sort?

Rickard
  • 1,289
  • 1
  • 17
  • 27
  • Can you post your C program, its hard to find out the problem otherwise. – Ashish Gaur Dec 01 '13 at 17:14
  • @snyder The program is huge, I just want to know if there's a way of ignoring multiple newlines in a row with either grep or sort? – Rickard Dec 01 '13 at 17:44
  • Your question isn't clear. Are you using C language to call shell programs or reimplementing the shell programs in your own C program? Are you calling one or two big piped shell commands or are you implementing your own pipeline in C? – Vorsprung Dec 01 '13 at 17:50
  • To remove blank lines, you can use a sed regex such as sed '/^\s*$/d' [see this stackoverflow post](http://stackoverflow.com/questions/16414410/delete-empty-lines-using-sed) – master_latch Dec 01 '13 at 17:51
  • @Vorsprung I'm using C to call and connect shell programs with pipes. Every program (grep, sort, less/more) is called in it's own child process and piped to the others. The parent process writes the environment variables to grep through a pipe. – Rickard Dec 01 '13 at 18:23
  • Does it work if you run the command sequence from standard shell? – hyde Dec 01 '13 at 19:02
  • Also, if you remove your extra `'\n'` print, does it then print just one big line? – hyde Dec 01 '13 at 19:04
  • 1
    @hyde Yes, and yes, it prints a bunch of newlines first, and then all the env. variables after eachother. – Rickard Dec 01 '13 at 19:08
  • Well then, I think problem is in code not shown. Perhaps there is a file descriptor mixup, some other writes going to that fd, or something. – hyde Dec 01 '13 at 19:17

3 Answers3

1

To filter out blank lines from an output stream:

... | grep . | ...

or, to filter out any line which consists only of spaces:

... | grep '\S' | ...
Tim Pierce
  • 5,514
  • 1
  • 15
  • 31
1

With grep you can filter out empty lines with

grep -v '^$'

With awk you can do more fancy things, like replacing multiple empty lines with just one:

awk '/^$/ {if (!e) {e=1;print}} /./ {e=0; print}'

This produces the following:

% (echo hello;echo;echo;echo;echo;echo world) | awk '/^$/ {if (!e) {e=1;print}} /./ {e=0; print}'
hello

world

Note the single empty line in the output.

Coroos
  • 371
  • 2
  • 9
0

On your loop that reads the final chunk of output, do something like this

int flag=1;
char prev='\n';
while(fgets(buf, f, sizeof(buf)) {
 if (buf[0]='\n' && prev='\n' && flag) next
 flag = 0;

If the first line is a single \n this will be skipped and so will any number of \n lines

Vorsprung
  • 32,923
  • 5
  • 39
  • 63