skip to Main Content

I have a file and I am trying to find and replace a string of text. The contents of the file are:

/**
 * Version:      1.5.1
 * Tested up to: 5.8
**/

I am trying to append the commit hash onto the version number inside of a file using a combination of awk and sed, but am having a difficult time. Previously, this was working just fine but is no longer working properly:

VERSION_LINE=$(awk '/* Version:/' style.css)
COMMIT_HASH=$(git rev-parse --verify HEAD | head -c 7)
sed -i -e "${VERSION_LINE}s/$/-${COMMIT_HASH}/" style.css

I expect $VERSION_LINE to return * Version: 1.5.1 but Checking contents it, it’s actually returning a bunch of file names (which don’t contain the string) AND that line at the end.

$ echo $VERSION_LINE;
404.php LICENSE archive.php comments.php dist footer.php functions.php header.php includes index.php page.php partials readme.txt screenshot.png search.php searchform.php single.php style.css woocommerce woocommerce.php Version: 1.5.1

But when I run awk '/* Version:/' style.css it does return the correct line, but storing it in a variable via VERSION_LINE=$(awk '/* Version:/' style.css) is returning a bunch of file names. Why the difference?

Trying the following is also returning the incorrect value:

$ $VERSION_LINE=$(cat style.css | grep '* Version:')
$ -bash: 404.php: command not found

Works Fine:

$ awk '/* Version:/' style.css
$ * Version:      1.5.1

Does Not Work:

$ VERSION_LINE=$(awk '/Version:/' style.css)
$ echo $VERSION_LINE
404.php Gruntfile.js LICENSE README.md archive.php changelog.txt comments.php composer.json composer.lock cypress.json docs footer.php functions.php header.php includes index.php languages manifest.xml package.json page.php partials phpcs.xml phpunit.xml postcss.config.js readme.txt screenshot.png search.php searchform.php single.php style.css vendor woocommerce woocommerce.php yarn.lock Version: 1.5.1

Current Version of Bash:

$ bash --version
$ GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu)

2

Answers


  1. You can do this with awk only:

    awk -v hash="${COMMIT_HASH}" '/* Version:/{$3=$3""hash}1' style.css > style.css.tmp 
        && mv style.css.tmp style.css
    
    Login or Signup to reply.
  2. The immediate problem is that you need to quote the assignment to prevent the shell from expanding the literal *:

    tripleee$ ls
    foo bar baz
    tripleee$ poo=$(echo '*')
    tripleee$ echo "$poo"
    foo bar baz
    tripleee$ poo="$(echo '*')"
    tripleee$ echo "$poo"
    *
    

    But the whole diversion to use Awk to find the line you want to replace is unnecessary (and basically a variation of Counting lines or enumerating line numbers so I can loop over them – why is this an anti-pattern?) — you can easily use sed itself to find the line.

    commit_hash=$(git rev-parse --verify HEAD | head -c 7)
    sed -i -e "/* Version:/s/$/-${commit_hash}/" style.css
    

    (Notice also the use of lower case for private variables.)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search