xenoterracide
xenoterracide

Reputation: 16837

gawk gensub regex, how do I replace one or more, with back to back similar capture groups

ok, here's my yet again evolved git awk script.

$2 ~ /\.puml$/ && $2 !~ /(theme|config)\.puml$/ \
{
  fn=gensub( /([[:alpha:][:digit:]\/-]+)\/([[:alpha:][:digit:]-]+)\.puml$/,"\\1/.svg/\\2-MODE.svg", "g", $2 )
  light=gensub(/MODE/, "light", "g", fn);
  dark=gensub(/MODE/, "dark", "g", fn);
  if( $1 !~ /^D$/ ) {
    # light changed svg
    lcs=lcs " " light
    dcs=dcs " " dark
  }
  else {
    lrs=lrs " " light
    drs=drs " " dark
  }
}
END {
  printf "::set-output name=changed-files::%s\n::warning::%s\n", lcs, lcs
  printf "::set-output name=changed-files::%s\n::warning::%s\n", dcs, dcs

  printf "::set-output name=removed-files::%s\n::warning::%s\n", lrs, lrs
  printf "::set-output name=removed-files::%s\n::warning::%s\n", drs, drs
}

you can run with

( cat << EOF                                                                                                                  
A       .config/plantuml/theme.puml
M       .github/workflows/main.yml
M       .github/workflows/plantuml.yml
M       README.md
A       app/gradle.lockfile
A       authn/gradle.lockfile
A       docs/README.md
A       docs/domain-model/README.md
A       docs/domain-model/user.md
A       docs/domain-model/user.puml
A       docs/domain-model/foo.puml
M       settings.gradle.kts
D       user.puml
D       foo.puml
EOF
) | awk -f git_file_changes.awk

this is the closest to working I've gotten. The problem is the regex is not what I need if the puml files are in the root directory. I get this:

::set-output name=changed-files:: docs/domain-model/.svg/user-light.svg docs/domain-model/.svg/foo-light.svg
::warning:: docs/domain-model/.svg/user-light.svg docs/domain-model/.svg/foo-light.svg
::set-output name=changed-files:: docs/domain-model/.svg/user-dark.svg docs/domain-model/.svg/foo-dark.svg
::warning:: docs/domain-model/.svg/user-dark.svg docs/domain-model/.svg/foo-dark.svg
::set-output name=removed-files:: user.puml foo.puml
::warning:: user.puml foo.puml
::set-output name=removed-files:: user.puml foo.puml
::warning:: user.puml foo.puml

the changed-files key is correct. Not because changed-files would be inherently correct, just because there are no root changed files. The output should be:

::set-output name=changed-files:: docs/domain-model/.svg/user-light.svg docs/domain-model/.svg/foo-light.svg
::warning:: docs/domain-model/.svg/user-light.svg docs/domain-model/.svg/foo-light.svg
::set-output name=changed-files:: docs/domain-model/.svg/user-dark.svg docs/domain-model/.svg/foo-dark.svg
::warning:: docs/domain-model/.svg/user-dark.svg docs/domain-model/.svg/foo-dark.svg
::set-output name=removed-files:: .svg/user-light.svg .svg/foo-light.svg
::warning:: .svg/user-light.svg .svg/foo-light-svg
::set-output name=removed-files:: .svg/user-dark.svg .svg/foo-dark.svg
::warning:: .svg/user-dark.svg .svg/foo-dark.svg

I did try to use a 0 or more match * but that just messes everything up

what should I do to get the desired output?

Upvotes: 1

Views: 112

Answers (1)

anubhava
anubhava

Reputation: 784898

You can make first capture group optional in gensub and make sure to capture last / in capture group #1 itself:

fn=gensub( /([[:alpha:][:digit:]\/-]+\/)?([[:alpha:][:digit:]-]+)\.puml$/,"\\1.svg/\\2-MODE.svg", "1", $2 )

Pay attention to: ([[:alpha:][:digit:]\/-]+\/)? which makes this group optional hence it matches user.puml and foo.puml as well.

With this change I am getting this output:

::set-output name=changed-files:: docs/domain-model/.svg/user-light.svg docs/domain-model/.svg/foo-light.svg
::warning:: docs/domain-model/.svg/user-light.svg docs/domain-model/.svg/foo-light.svg
::set-output name=changed-files:: docs/domain-model/.svg/user-dark.svg docs/domain-model/.svg/foo-dark.svg
::warning:: docs/domain-model/.svg/user-dark.svg docs/domain-model/.svg/foo-dark.svg
::set-output name=removed-files:: .svg/user-light.svg .svg/foo-light.svg
::warning:: .svg/user-light.svg .svg/foo-light.svg
::set-output name=removed-files:: .svg/user-dark.svg .svg/foo-dark.svg
::warning:: .svg/user-dark.svg .svg/foo-dark.svg

Upvotes: 3

Related Questions