Saturday, May 28, 2022

[SOLVED] How to find and replace string in a file WITHOUT sed

Issue

This is for my setup repo which I use in fresh linux installs and company provided macbooks. I have this makefile target:

omz-theme:
    sed -i 's/ZSH_THEME=".*"/ZSH_THEME="$(THEME)"/g' $(HOME)/.zshrc

This works fine on linux but breaks on macs because they use BSD's sed. I need some way to find and replace text in my .zshrc that will run regardless of the system. Almost all resources online point only to sed.

Edit: This is how it "breaks" on mac. Doesn't happen if I do brew install gnu-sed and change the target to use gsed

sed: 1: "/Users/username/.zshrc": unterminated substitute pattern


Solution

You can use awk for find and replace as well. Here's a resource with more detail..

For example, your makefile command could be replaced with:

omz-theme:
    awk -v var="ZSH_THEME=$(echo THEME)" '{sub(/^ZSH_THEME=.*$/, var); print}' $(HOME)/.zshrc

You could use this to overwrite the existing $(HOME)/.zshrc file using redirection:

omz-theme:
    awk -v var="ZSH_THEME=$(echo THEME)" '{sub(/^ZSH_THEME=.*$/, var); print}' $(HOME)/.zshrc > $(HOME)/.zshrc

Alternately, you could check the OS using OSTYPE and then use the correct sed syntax for BSD and GNU:

omz-theme:
    if [[ "$OSTYPE" == "linux-gnu"* ]]; then 
        sed -i 's/ZSH_THEME=".*"/ZSH_THEME="$(THEME)"/g' $(HOME)/.zshrc
    else
        sed -i '' 's/ZSH_THEME=".*"/ZSH_THEME="$(THEME)"/g' $(HOME)/.zshrc
    fi

(note: I didn't test the above, but you get the idea)



Answered By - logyball
Answer Checked By - Katrina (WPSolving Volunteer)