I had to modify a complex file in a Dockerfile. While sed was working, it wasn't very readable. I didn't want to use Python because then I'd have to install it unnecessarily. I ended up using awk because of its availability and its purpose that met my needs. I'll use a made up example here to demonstrate what the awk script would look like. Let's assume we are modifying the [Declaration of Independence](https://www.archives.gov/founding-docs/declaration-transcript). ``` #!/usr/bin/awk -f BEGIN {} { inputline = $0; gsub(/Brittish brethren/, "allies across the pond", inputline); print inputline; } END {} ``` The first line (the crunchbang line) is setting the path of awk we want to use as well as using the [-f flag](https://www.man7.org/linux/man-pages/man1/awk.1p.html) to set the file name to use i.e. this file we are running. Let's say we called it decl.awk. We would make it executable and run it like below. Now it would run successfully. ``` $ chmod u+x decl.awk $ ./decl.awk ``` awk uses pattern-action pairs to process input lines. There are two special pairs or blocks: BEGIN and END. These blocks runs only once, at the beginning and the end of the process respectively. All other pairs or blocks run for each input line. In BEGIN we can initialize variables. In END we can finalize things, such as printing summaries. In our example we don't need to use either of those. awk has a special variable $0 which represents the input line. We save it in our own variable. Since this variable is set for each input line, we can't save it in BEGIN. Next we use the gsub function. It makes a regular expression search on the input line and replaces all results with the replacement string. The last argument to gsub is our variable. In our example, we are searching for string "Brittish brethren" in each line of the declaration. It only appears once and so we expect it to be replaced by "allies across the pond" only once. We can use gsub as many times as we want, each time replacing a different pattern. Finally, we print each line back to stdout, whether it was replaced or not. This is how we would use the script, ``` $ curl -s https://www.archives.gov/founding-docs/declaration-transcript | ./decl.awk | grep 'allies across the pond'
Nor have We been wanting in attentions to our allies across the pond. We have warned them from time to time of attempts by their legislature to extend an unwarrantable jurisdiction over us. We have reminded them of the circumstances of our emigration and settlement here. We have appealed to their native justice and magnanimity, and we have conjured them by the ties of our common kindred to disavow these usurpations, which, would inevitably interrupt our connections and correspondence. They too have been deaf to the voice of justice and of consanguinity. We must, therefore, acquiesce in the necessity, which denounces our Separation, and hold them, as we hold the rest of mankind, Enemies in War, in Peace Friends.
``` Without our script grep can't find the changed string. That's how we know our script was successfully written and executed. ``` $ curl -s https://www.archives.gov/founding-docs/declaration-transcript | grep 'allies across the pond'; echo $? 1 ``` This technique could also be used in place of sed in [Add FIPS Module to OpenSSL 3.0.11 on Debian 12 Bookworm](link://slug/add-fips-module-to-openssl-3011-on-debian-12-bookworm). See more: [Use of BEGIN and END Rules in Awk](https://www.baeldung.com/linux/awk-begin-and-end-rules).