2

I think I've done this a couple of times but I can't do it this morning. I have a file like this for example. (this is the result of comparison of many files using foreach and diff, with file names enclosed with ### pattern)

<< file gg >>

### ./translations/qt_fr.ts ###
### ./translations/qt_es.ts ###
### ./translations/qt_help_hu.ts ###
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###

what I want to do is remove those lines with only file name to produce output like below.

(expected output)

### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1

How can I do this wit awk? I tried this(I tried to make it look like C, the same). I call the line with ### 'header' line. The logic is : I print all the non-header line, but if the previous line was a header, print the previous line. For this, I keep any header line in the 'kept' variable.

<< file tt.awk >>

{if ($0 !~ /^###/)
        if (flag == 1) {print $kept; print $0;}
        else {print $0}
}

{if  ($0 ~ /^###/)
        flag = 1;
else
        flag = 0;
kept = $0;
}

When I run awk -f tt.awk gg, I get this result. The 'kept' is not from the previous line but the current line. What's wrong with the awk code? A long-time awk user, I maybe missing something important.

< alala0
< alala0
------
> blabla0
< alala0
< alala0
< alala1
--------
> blabla0
> blabla1
Chan Kim
  • 5,177
  • 12
  • 57
  • 112
  • 1
    The problem is `$kept`. You don't use `$` on normal awk variables. `$1`, etc. are the actual names. So you want `print kept`. That being said the other changes in John1024's answer are also good. Use the built-in pattern matching actions rather than `if`, etc. – Etan Reisner Feb 12 '15 at 02:32

3 Answers3

3

To make the existing code work, replace:

    if (flag == 1) {print $kept; print $0;}

With:

    if (flag == 1) {print kept; print $0;}

Other approaches

$ awk '/^###/{kept=$0;f=1;next} f {print kept} {f=0;print}' gg
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1

For simplicity, the flag f can be eliminated:

$ awk '/^###/{kept=$0;next} kept {print kept} {kept="";print}' gg
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
John1024
  • 109,961
  • 14
  • 137
  • 171
2

What you want is simpler:

{
    if ($0 ~ /^###/)
    { kept = $0; flag=1; }
    else if (flag == 1) {print kept; print $0; flag=0}
    else {print $0}
}
stark
  • 12,615
  • 3
  • 33
  • 50
1

using a sed approach

sed '/^###.*###/d' file

find all lines with patter and delete or

sed -n '/^###.*###/!p' file

find all lines without pattern ### and print

repzero
  • 8,254
  • 2
  • 18
  • 40