0

I have been trying to automate something, using sed in a loop I wanted to do this:

while IFS= read -r line; do
  sed -r -i '' "\"s|::set-output name=(.*)::(.*)\"|\"\1=\2\" >> \$GITHUB_OUTPUT|p" "$line"
done < <(grep -RIl "::set-output" | sort -u)

This should feed a list of files returned by grep which match the pattern to sed, which should replace each line with a similar line that matches the new format I want.

This seems to work fine, but it has some unintended results that I cannot explain, every time it replaces one line, it results in two new lines. I don't know what behaviour is causing this and my initial searches around the subject haven't resulted in much useful information and I am not sure what to look in to.

To reproduce the issue, I set -x, ran my loop and grabbed one of the lines from the debug output. I reset my repo back to default with git stash and then did:

$ sed -r -i '' 's|"::set-output name=(.*)::(.*)"|"\1=\2" >> $GITHUB_OUTPUT|p' ./.github/workflows/platform-status.yml

Now I can see in the git diff that it has replaced my old line with two identical lines:

-          echo "::set-output name=version::${VERSION}"
+          echo "version=${VERSION}" >> $GITHUB_OUTPUT
+          echo "version=${VERSION}" >> $GITHUB_OUTPUT

I don't understand where the second line is coming from and I wouldn't expect this behaviour from sed, can anyone tell me what I am doing wrong?

6
  • As this might be hard to reproduce by others, can you create a sample input file (basically by running the grep part) and add this to the question?
    – nohillside
    Commented Apr 25, 2023 at 15:54
  • Try with the -n flag. I mostly stopped using sed in favor of awk but if memory serves, sed will by default print the results in addition to explicit print commands. The -n flag will suppress printing except for explicit print commands.
    – Allan
    Commented Apr 25, 2023 at 15:55
  • Thanks @Allan, I originally used sed -rn -i but when I tried that it removed everything in the file and replaced it with just the lines it should have written in the file. maybe I should try to fix that instead...
    – Rumbles
    Commented Apr 25, 2023 at 19:00
  • That behavior doesn’t sound right. sed should only be replacing text it matches. If it’s matching everything and only writing when the pattern is matched, there’s something major missing there. The -i flag will write the changes in place. Try writing to a new file to see if it works as expected (just for diagnosis)
    – Allan
    Commented Apr 25, 2023 at 19:15
  • Here’s a sed command I used (on FreeBSD, but should work on macOS) to remove the comment (#) from the wheel line in sudoers. This parses the whole file and only changes the relevant line: sed -n -i .backup '/^# %wheel ALL=(ALL) ALL/ s/^#//' ${FILE}. The .backup makes a backup file automatically with that extension.
    – Allan
    Commented Apr 25, 2023 at 19:20

1 Answer 1

1

I found a post on Stack Overflow, which suggested using perl instead:

sed -r -i ''

becomes

perl -pi -e

And it works exactly as I would expect

1
  • A decent workaround and easy to test for others. +1 even if Apple stops shipping perl it should be widely available and installable if it should get dropped in an update to the OS.
    – bmike
    Commented Apr 25, 2023 at 19:35

You must log in to answer this question.

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