Not sure I follow. Is there anything wrong with the following approach:
ex testfile <<EOF
The trick is to position the cursor at the end line, so that searching forwards will find the match at the beginning of the file. Same for searching backwards, position the cursor at the first line and then search backwards.
Those requirements make relying solely on pattern-ranges tricky...perhaps even impossible though I didn't spend too much time thinking about it. Instead I figured I'd go the KISS route and use a search and mark approach and then use the marks as a range to be printed.
I'll lay it all out on individual lines:
call search('sta', 'c') : search forward for '...
The format for :m[ove] is
Where the range is the line or lines you want to move and the address is the target. Note that the moved line(s) will actually be placed on the line below the address.
So you're looking for a range of "mark a" and an address of "the current line". You can find all the special names for ...