en fr

Move line matching a regexp in bash

Posted on 2015-07-22 in Trucs et astuces

Recently I had to update the closure compiler on a project. To do so, I had to move some code lines used by closure: the compiler uses goog.require and goog.provide to manage dependencies. In the version used by the project, these lines were in an IEF:

(function() {
       goog.require('toto');
       goog.provide('titi');

But this way to write code is not possible any more with newer versions of the closure compiler: dependencies must be managed at file level. goog.require and goog.provide must be moved out of the IEF. Since lost of files were to be updated, I wrote the following script to automate the process.

# Loop on all files that have an IEF in source folder
for file in $(grep -rl '^(function() {' src | grep -v lib); do
    # Remove the first line of the IEF
    sed -i '/^(function() {/d' "${file}"
    # Remove goog.* indent
    sed -i -r 's/^  (goog.(provide|require))/\1/g' "${file}"
    # Print the file from bottom to top.
    # For the fist line concerning dependencies management, we print the
    # first line of the IEF and we print the dep line.
    # Reverse the file again.
    tac "${file}" | awk '/goog.(provide|require)/ && ! seen {print "(function() {"; seen=1} {print}' | tac > "${file}.new"
    # We must use a new file because due to the pipes, the file may get
    # written before it is completely read. That will prevent the script to
    # work as expected.
    mv -f "${file}.new" "${file}"
done