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? Commented Jul 26, 2022 at 14:27
  • yes the pattern varies Commented 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 ! Commented 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 Commented Jul 26, 2022 at 22:08
  • @steeldriver cool Thanks!. :) Didn't know ed had the g command Commented 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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.