2

I’ve a large number of text files in a directory and want to cut and paste the first comment section to be at the start of the file (the length and start point of the comment text varies, in some cases it might not be present, but should be in first 50 lines). I’m thinking of using some bash code to work through all the files and then use sed on each filename to cut the first block of comment text enclosed between ''' and ''' to be moved to the top of file. I'm struggling with what i think needs to be a nested a sed command, initially using sed to find the matching block of text and then using the sed hold space. Ubuntu 23.04

Original sample:

from itertools import permutations
import time

'''
Here is some comment text
that should be at start of file
some more lines
'''

def somepythoncode(x):
    return x+1

Target:

'''
Here is some comment text
that should be at start of file
some more lines
'''
from itertools import permutations
import time

def somepythoncode(x):
    return x+1

3 Answers 3

4

With ed:

printf '%s\n' "/^'''$/; // m 0" wq | ed -s file.py
  • /^'''$/; will move the cursor to the first line that matches the given expression.
  • m 0 will move the addressed lines to the line after line zero (i.e., insert them at the top). The address is //, which means that the most recently matched regular expression, ^'''$, will be reused. This will be used as the end address for the command. The start address is implicitly . (the current line).
  • wq to write back the changes to the file.

You can use /^'''$/; //+1 m 0 to extend the ending range by another line.

2
  • 1
    Edited. Let me know if you want me to tweak it.
    – Kusalananda
    Oct 27, 2023 at 15:50
  • 1
    This worked great. Thank you for the clear explanation, I've got a lot to learn!
    – Guy
    Nov 13, 2023 at 17:49
2

Using any awk:

$ cat whatever.py
from itertools import permutations
import time

'''
Here is some comment text
that should be at start of file
some more lines
'''

def somepythoncode(x):
    return x+1

$ cat tst.sh
#!/usr/bin/env bash

for file; do
    awk -v delim="'''" '
        $0 == delim { dnr[++cnt] = NR }
        { rec[NR] = $0 }
        END {
            if ( 2 in dnr ) {
                for ( i=dnr[1]; i<=dnr[2]; i++ ) {
                    print rec[i] > FILENAME
                    delete rec[i]
                }
                for ( i=1; i<=NR; i++ ) {
                    if ( i in rec ) {
                        print rec[i] > FILENAME
                    }
                }
            }
        }
    ' "$file"
done

$ ./tst.sh whatever.py

$ cat whatever.py
'''
Here is some comment text
that should be at start of file
some more lines
'''
from itertools import permutations
import time


def somepythoncode(x):
    return x+1

The above assumes your files aren't too huge to fit in memory, i.e. are less than several million lines long.

0
0

You could extract the comment block with:

$ awk "/'''/{p=! p;print;next}p" infile 
'''
Here is some comment text
that should be at start of file
some more lines
'''

You will then be left with:

$ awk "/'''/{p=! p;next};p==0{print}" infile 
from itertools import permutations
import time


def somepythoncode(x):
    return x+1

Combining the two will give you the final result:

$ (awk "/'''/{p=! p;print;next}p" infile; awk "/'''/{p=! p;next};p==0{print}" infile)
'''
Here is some comment text
that should be at start of file
some more lines
'''
from itertools import permutations
import time


def somepythoncode(x):
    return x+1

You must log in to answer this question.

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