1

I have a file in which a pattern (eg: RotX) is repeated many times in a similar context. I need to insert a specific text (eg: Rot-X) at the start of every line which is located five lines before every pattern match:

...

_face_641
{
    type wall;
    nFaces 6;
    startFace 63948413;
    inGroups       1(RotX);
}

_face_821
{
    type wall;
    nFaces 3;
    startFace 63948419;
    inGroups       1(RotX);
}

_face_67
{
    type wall;
    nFaces 3;
    startFace 63948422;
    inGroups       1(RotX);
}

...

should become

...

Rot-X_face_641
{
    type wall;
    nFaces 6;
    startFace 63948413;
    inGroups       1(RotX);
}

Rot-X_face_821
{
    type wall;
    nFaces 3;
    startFace 63948419;
    inGroups       1(RotX);
}

Rot-X_face_67
{
    type wall;
    nFaces 3;
    startFace 63948422;
    inGroups       1(RotX);
}

...        

Could this be done using sed or awk ?

Many thanks in advance for your help

2
  • 1
    Does the pattern change? For example, could you just preface every line that starts with _ with Rot-X? Or does the pattern within your parentheses vary such that it's not always Rot-X where RotX is found 5 lines later?
    – Marc
    Jul 26, 2022 at 14:27
  • yes the pattern varies
    – OlM
    Jul 26, 2022 at 15:16

3 Answers 3

1

Using a simple 2-pass approach:

$ awk 'NR==FNR{ if (/RotX/) nrs[NR-5]; next } FNR in nrs{ $0="Rot-X" $0 } 1' file file
...

Rot-X_face_641
{
    type wall;
    nFaces 6;
    startFace 63948413;
    inGroups       1(RotX);
}

Rot-X_face_821
{
    type wall;
    nFaces 3;
    startFace 63948419;
    inGroups       1(RotX);
}

Rot-X_face_67
{
    type wall;
    nFaces 3;
    startFace 63948422;
    inGroups       1(RotX);
}

...
1
  • 1
    I tried the 2-pass approach. It works perfectly. Wonderful ! A great thank you to you Ed !
    – OlM
    Jul 27, 2022 at 10:26
1

Using vim

vim -c "g/RotX/norm 5kIRot-x" -c "wq" file.txt

Using ed: From @steeldriver

printf '%s\n' 'g/(RotX)/-5s/^/Rot-X/' 'wq' | ed -s file.txt

If the braces {, need not be exactly 4 lines above but otherwise same format,

vim -c "g/RotX/norm [{kIRot-X" -c "wq" file.txt
printf "%s\n" 'g/RotX/?^{$?-1s/^/Rot-X/' 'wq' | ed -s file.txt
2
  • 1
    ... or similarly using ed, printf '%s\n' 'g/(RotX)/-5s/^/Rot-X/' 'wq' | ed -s file.txt Jul 26, 2022 at 22:08
  • @steeldriver cool Thanks!. :) Didn't know ed had the g command
    – balki
    Jul 27, 2022 at 2:01
0

A single pass with awk:

# insert_before_match.awk
{
    p6=p5
    p5=p4
    p4=p3
    p3=p2
    p2=p1
    p1=$0

    if ($0 ~ /RotX/) {
        print "Rot-X"p6
        print p5
        print p4
        print p3
        print p2
        print p1
        print "}"
        print ""
    }

}

$ awk -f insert_before_match.awk infile

Rot-X_face_641
{
    type wall;
    nFaces 6;
    startFace 63948413;
    inGroups       1(RotX);
}

Rot-X_face_821
{
    type wall;
    nFaces 3;
    startFace 63948419;
    inGroups       1(RotX);
}

Rot-X_face_67
{
    type wall;
    nFaces 3;
    startFace 63948422;
    inGroups       1(RotX);
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .