Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am trying to reorder generated output as follows; given a tex fragment as follows, I want to move the /^Constant/ down below /Dummies/, with the line before and after /^Constant/. Further, I would like a stable result, one that does not make a change if Constant is already below the last Dummies row (it runs as part of a script to fix up my research results, and so far that script is stable).

This is the tex fragment input:

[1em]
Application Grade&                  &                  &  -0.0857\sym{***}& -0.00412\sym{***}\\
                &                  &                  & (0.0149)         &(0.00107)         \\
[1em]
Constant        &   -3.701\sym{***}&   -0.311\sym{***}&        0         &        0         \\
                &  (1.130)         & (0.0853)         &      (.)         &      (.)         \\
[1em]
Major Dummies   &       No         &       No         &      Yes         &      Yes         \\
[1em]
Semester Dummies &       No         &       No         &      Yes         &      Yes         \\
\hline

This is the desired output, which remains stable (returns the same) if given as input:

[1em]
Application Grade&                  &                  &  -0.0857\sym{***}& -0.00412\sym{***}\\
                &                  &                  & (0.0149)         &(0.00107)         \\
[1em]
Major Dummies   &       No         &       No         &      Yes         &      Yes         \\
[1em]
Semester Dummies &       No         &       No         &      Yes         &      Yes         \\
[1em]
Constant        &   -3.701\sym{***}&   -0.311\sym{***}&        0         &        0         \\
                &  (1.130)         & (0.0853)         &      (.)         &      (.)         \\
\hline

The following code will do so, but it is not stable. Basically it matches on Constant, drops and re-inserts [1em] (which it has to do on a separate call since i\ affects the output, not the pattern space), and pastes below the target. It's not stable because it will add bogus [1em]s after Semester Dummies. Frankly, its a bit ugly (requiring separate calls to sed).

sed -E -i'' -e'/^Constant/ {N;h;N;d;}; /^Semester Dummies/ {G;};' fragment.tex
sed -E -i'' -e '/^Semester Dummies/ {a\
\[1em\]
};' fragment.tex

I believe a one-liner will do it, matching the multiline pattern /^\[1em\]\nConstant.*/ (after a call to N;N;), putting this in the hold buffer, and then pasting it (G;) after /Semester Dummies/. But after many hours, man pages, web searches, and upgrading to gnused for good measure, I cannot get such a script to work. This expresses the basic idea but is not valid (s cannot conditionally hold as I do here):

sed -E -i'' -e'/\[1em\]/ {N;N;s/^\[1em\]\nConstant.*//h;}; /Semester Dummies/ {G;}' fragment.tex

I tried many variations relying on N;P;D;h;G; with various addressing but I still don't understand the execution order for multiply addressed commands when you are messing with the pattern space (calling N;). N and P work nicely, but as far as I can tell, D is completely useless.

Yes, I know it is easier with awk and perl; in fact, I would be interested in seeing all three solutions for comparison--but here I am specifically asking how to do it in sed.

share|improve this question

1 Answer 1

Here's an ugly piece of awk that plays tricks with the record separator

awk -v RS='\\[1em\\]\n|\\\\hline' '
    !/[^[:space:]]/ {next} 
    /^Constant/ {c=$0; next} 
    {printf "[1em]\n%s", $0} 
    END {printf "[1em]\n%s\\hline\n", c}
'

Since the text starts and ends with "record separator", there are some spurious empty-ish records, hence the first rule

share|improve this answer
    
This is helpful, though it produces somewhat corrupted output (it seems to replace any backslashes present in the source tex file with '[1em]\n' (a real newline)). I think awk is probably the right tool for this anyway, so thanks for the hints. –  rjturn Feb 25 at 21:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.