1

I am trying to use sed to replace node version matches in certain files

The following is what I have come up with but it leaves certain digits or characters after replacement and is not replacing the whole match and is rather pretending the replacement to the existing text.

find . -type f -exec sed -i "s/nodejs\d*.x/nodejs18.x/" {} \;

currently the above does not work at all

Sample:

module "lambda_function" {
  source                 = "git::ssh://[email protected]/pizzahutuk/infra-module-lambda?ref=v4.5.11"
  runtime                = "nodejs16.x"
}

In the above example nodejs16.x should be changed to nodejs18.x

6
  • Is this a structured document written in HCL?
    – Kusalananda
    Commented Mar 20, 2023 at 14:15
  • @Kusalananda yes
    – xerxes
    Commented Mar 20, 2023 at 14:21
  • 1
    @JJoao Although the dot in nodejs[0-9]*.x would match the dot given OP's example, in the regex context it means any character, but what needs to be matched is a literal dot, so it should be nodejs[0-9]*\.x. Commented Mar 20, 2023 at 15:22
  • Kusalananda gave you the correct solution, but just FYI, sed doesn't understand \d which is a PCRE feature. So \d in sed is just the letter d and nothing else. So that's why your approach didn't work, sed was looking for nodejs followed by 0 or more d characters, then any character (.) and an x and since you have numbers after the nodejs string, that wouldn't match.
    – terdon
    Commented Mar 20, 2023 at 16:44
  • @terdon And (or) they are using the native sed on macOS, which treats -i differently. It's unfortunately quite unclear what "does not work at all" actually means here, so we are left guessing and trying to cover all possible ways things could possibly have gone wrong.
    – Kusalananda
    Commented Mar 20, 2023 at 17:11

1 Answer 1

1

Using the HCL processor hclq from Matthew Olenik (mattolenik on Github) (install with e.g. go install github.com/mattolenik/hclq@latest):

$ hclq set -i file module.lambda_function.runtime nodejs18.x
module "lambda_function" {
  source  = "git::ssh://[email protected]/pizzahutuk/infra-module-lambda?ref=v4.5.11"
  runtime = "nodejs18.x"
}

This reads the HCL document from the file called file. It sets the value of the runtime key to nodejs18.x when this key occurs in the lambda_function module. If you used --in-place, the modification would be done in-place.

You may relax the query path by using a wildcard character:

$ hclq -i file set 'module.*.runtime' nodejs18.x
module "lambda_function" {
  source  = "git::ssh://[email protected]/pizzahutuk/infra-module-lambda?ref=v4.5.11"
  runtime = "nodejs18.x"
}

You may also use set replace to only replace specific strings:

$ hclq -i file set replace 'module.*.runtime' nodejs16.x nodejs18.x
module "lambda_function" {
  source  = "git::ssh://[email protected]/pizzahutuk/infra-module-lambda?ref=v4.5.11"
  runtime = "nodejs18.x"
}

In the above command, the runtime key's value would not be replaced with nodejs18.x unless it had the original value nodejs16.x.

Applying this to all files in the current directory and below could be done with find:

find . -type f -exec hclq -i {} --in-place set replace 'module.*.runtime' nodejs16.x nodejs18.x \;

If you would rather use sed to replace any occurrence of any NodeJS string, you may use

find . -type f -exec sed -i 's/nodejs[0-9]*\.x/nodejs18.x/' {} +

This assumes you have a sed that understands the -i option as shown (FreeBSD and macOS use -i '' for in-place editing with no backup file). The \d thing you tried to use in your question is a Perl-compatible regular expression pattern, also supported by GNU regular expressions. For portability, use either [0-9] as shown above, or [[:digit:]]. I escaped the dot in the pattern to match a literal dot instead of "any character", which the special . pattern usually matches.

3
  • is it possible to make the regex option non system dependent?
    – xerxes
    Commented Mar 20, 2023 at 17:19
  • In GNU sed 4.7, \d097 matches byte 97 (decimal), same as \x61 (a in ASCII). In ast-open's sed, \d matches a decimal digit like in perl Commented Mar 20, 2023 at 17:28
  • @xerxes Yes, use POSIX basic regular expressions (my answer does that), and don't use -i (write the output to a new file and then move that to the original file, is one way of doing that).
    – Kusalananda
    Commented Mar 20, 2023 at 18:55

You must log in to answer this question.

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