1

Output error from the execution of sed command:

sed: -e expression #1, char 14: unterminated `s' command

command file that I am trying to execute:

#!/bin/sh

old_version='\"version\": \"0.0.0\"'

year=$(date +%y)
dayOfYear=$(date +%j)

version=$year'.'$dayOfYear'.''3434'
echo $version

filepath="/opt/vsts-agent-linux/_work/5/s/projects/tl-angular-map/package.json"

echo $filepath

replace="s/"$old_version"/"$version"/g"

echo $replace

sed -i -e $replace $filepath

The problem is that the string that I am buiding from concatenation is not properly closed because of the double quotes in it.

1
  • The old_version variable contents contain literal backslashes: your json data most likely does not. See 3.1.2.2 Single Quotes in the manual Commented Oct 19, 2021 at 16:06

2 Answers 2

1

Assuming version is a top-level key in your JSON document, you would update it to the value that you want using jq like so:

jq --arg patch 3434 \
   '.version |= (now | strftime("%y.%j.") + $patch)' file.json >newfile.json

This first sets the internal variable $patch to the patch release version on the command line. It then formats a time-stamp string from the current time using strftime() and adds the value of $patch on to the end of that string. This resulting string is then assigned to the version key at the top-level of the JSON document, and the resulting document is outputted.

Example:

$ cat file.json
{
  "key": "value",
  "version": "0.0.0",
  "foo": "bar"
}
$ jq --arg patch 3434 '.version |= (now | strftime("%y.%j.") + $patch)' file.json
{
  "key": "value",
  "version": "21.292.3434",
  "foo": "bar"
}

Would you need to make sure that the old version is not updated if it is anything other than exactly 0.0.0, then instead use

jq --arg patch 3434 \
    'select(.version == "0.0.0").version |= (now | strftime("%y.%j.") + $patch)' file.json >newfile.json

That is, use select() to ensure that the object is only ever updated if its version value is 0.0.0.

An alternative way of formulating this, which may look nicer to some:

jq --arg patch 3434 \
    '(now | strftime("%y.%j.") + $patch) as $version |
    select(.version == "0.0.0").version |= $version' file.json >newfile.json
0

Adding literal quotes into strings doesn't mean that the shell understands those quotes. You want this (note, in bash version 4.2+, printf can be used for date formatting)

old_version='"version": "0.0.0"'

# "-1" is a magic value meaning "now"
printf -v year '%(%y)T' -1
printf -v dayOfYear '$(%j)T' -1

version="$year.$dayOfYear.3434"
echo "$version"
# or even without the temp variables:
# printf -v version '%(%y)T.%(%j)T.3434' -1 -1

filepath="/opt/vsts-agent-linux/_work/5/s/projects/tl-angular-map/package.json"
echo "$filepath"

replace="s/$old_version/$version/g"
echo "$replace"

sed -i -e "$replace" "$filepath"

However, this will replace the string "version": "0.0.0" with 21.292.3434, breaking your JSON object in the file.

$ cat package.json
{
  "key": "value",
  "version": "0.0.0",
  "foo": "bar"
}

$ sed "s/$old_version/$version/g" package.json
{
  "key": "value",
  21.292.3434,
  "foo": "bar"
}

What you should be using to manipulate JSON data is to set the new value:

$ jq --arg newversion "$version" '.version = $newversion' package.json
{
  "key": "value",
  "version": "21.292.3434",
  "foo": "bar"
}
3
  • 1
    Thanks for the suggestion! Although I still can't understand how to escape the double quotes in my string, to properly compose sed command Commented Oct 19, 2021 at 17:02
  • jq does the job! Commented Oct 19, 2021 at 17:30
  • You don't need to escape any quotes in the string. You just need to make sure the variables are quoted when you use them. As I demonstrate in my answer. Commented Oct 19, 2021 at 20:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .