Portable and efficient way to add text after pattern

Shell: sh/bash
OS: Linux (all unix flavors)

Suppose i have a variable with this content:

ArgZ='
import os
import sys
MySpecialpath = os.path.abspath(sys.argv[0])
#
'
ArgZB='#REGEN
#REGEN
#REGEN
'

I want to add this text to a file/script, only under the following conditions:

  1. First, scan the file/script and verify that the first 2 lines of the ArgZ variable dont already exist in it. Meaning, make sure the exact patterns of "^import os$" and "^import sys$" aren't anywhere in the script. If they are, remove them.

  2. Add the content of ArgZ and ArgZB only after the last line in the file/script that begins with an "import".

  3. If there are no lines in the file/script that has an import, add the content of ArgZ and ArgZB to the top of the file/script right under the "#\!" line.

  4. If a "#!" line does not exist, simply add the content of ArgZ and ArgZB to the top of the file/script.

So for example, if i have a file/script like the below:

#!/usr/bin/env python2.7

import sys
import time
import re
import os.path
from bisect import bisect_left

the code i'm looking for should make the output look like this:

#!/usr/bin/env python2.7

import os
import sys
MySpecialpath = os.path.abspath(sys.argv[0])
#
#REGEN
#REGEN
#REGEN
from bisect import bisect_left

or like this:

import os
import sys
MySpecialpath = os.path.abspath(sys.argv[0])
#
#REGEN
#REGEN
#REGEN
from bisect import bisect_left

what i was doing was greatly inefficient:

TheScript=$(cat file/script)
printf '%s\n' "${ArgsZ}""${ArgsZB}""${TheScript}" 

There's no logic here and im just adding the content to the beginning of the file/script. I want some logic applied to this.

Hi,

Maybe something like as :

awk -vArgz="$ArgZ" -vArgZB="$ArgZB" 'BEGIN{split(Argz,A,"\n")}
FNR == 1 {Line=0}
FNR == 1 && $0 ~ /^#!/ {Line=FNR}
$0 == A[2] || $0 == A[3]{next}
/^import/ {Line=FNR}
{B[FNR]=$0}
END{B[Line]=B[Line] Argz ArgZB;for (ll in B){print B[ll]}}' file

With your file example:

#!/usr/bin/env python2.7

import time
import re
import os.path
import os
import sys
MySpecialpath = os.path.abspath(sys.argv[0])
#
#REGEN
#REGEN
#REGEN

from bisect import bisect_left

This awk reads the file once and only once.

Regards.

1 Like