I have to insert a line into a configuration files automatically, but with the added caveat that it should be inserted before a multi-line footer comment and any preceding empty or whitespace-only lines if the footer exists. That is, the new line should be inserted right after the last configuration line, making for a single-line diff from the original file. In pseudo-code:
- Go to the end of the file.
- Go backwards to the first (that is, last in the file) configuration line (that is, a line which is not empty, whitespace-only, comment only or whitespace followed by a comment).
- Insert text after the current line.
Extended regular expression for configuration line: ^\s*[^[:space:]#]
Any common *nix tools such as sed
, awk
, ed
or ex
should work.
Possible solutions and their problems:
- Use
tac
twice to make this into a forward-searching problem rather than backward-searching. This means I'll have to store the result in a temporary file then replace the original, rather than doing this in a single command. - Use
sed -i
with the reversal trick. This means storing the entire file in memory. ex -c '1' -c '?^\s*[^[:space:]#]?' -c $'a\nmy new line\n.' -c 'wq' /path
, which I'm also given to understand stores the full file in memory.
Is there a solution which circumvents both of these issues?
Example starting file:
# Universe configuration
#
pi = 3 # A good #
e = mc**2 # To within a hair
[cut 200 trillion lines]
#
# END
#
Example input:
sol { mass = 42, start = 9.2 }
Expected output:
# Universe configuration
#
pi = 3 # A good #
e = mc**2 # To within a hair
[cut 200 trillion lines]
sol { mass = 42, start = 9.2 }
#
# END
#
General-purpose function based on @StephaneChazelas's solution
Best Answer
You could do something along these lines:
That overwrites the file in place and only stores the footer in memory. It needs the non-standard GNU
tac
command. The file has to be a regular text file.