0

I'm trying to adapt the answer from https://stackoverflow.com/a/66365284/1236401 that adds control flow to provide match status code:

cat file.txt | sed 's/1/replaced-it/;tx;q1;:x'

It works as expected on Ubuntu and Alpine, but fails on Mac OSX (11.6), using any shell.

sed: 1: "s/1/replaced-it/;tx;q1;:x": undefined label 'x;q1;:x'

All references I could find to sed misbehaving on OSX were for in-place file edit, which is not the case here.

Rob
  • 14,746
  • 28
  • 47
  • 65
Mugen
  • 8,301
  • 10
  • 62
  • 140
  • 1
    The question has been answered, but for reference, from the POSIX man page: `Command verbs other than {, a, b, c, i, r, t, w, :, and # can be followed by a , optional characters, and another command verb.`. For these commands you can use a new line, or break in to chunks with `-e` (which is also POSIX). "undefined label" is BSD sed accepting `;` in a label, whilst in GNU, the command separator meaning takes precedence (which is a deviation from the standard). – dan Nov 24 '21 at 11:38
  • sed is a great tool for doing simple s/old/new/ substitutions on individual lines but if you have any other text manipulation to do the code to do it will be some combination of clearer, more robust, more portable, and more efficient if you use awk. Idk what that sed incantation does so idk if @triplee's answer is the awk equivalent or not - if it isn't and you add concise, testable sample input and expected output and an `awk` tag we can help you. – Ed Morton Nov 24 '21 at 15:36
  • This could be written `sed '/1/{s//replaced-it/;q1}' file` or `sed '/1/!b;s//replace-it/;q1' file`. – potong Nov 24 '21 at 17:29

3 Answers3

3

Commands in sed are separated primarily by newlines.

| sed 's/1/replaced-it/
  tx
  q1
  :x
'

Alternatively:

sed -e 's/1/replaced-it/' -e 'tx' -e 'q1' -e ':x'

Additionally q1 is a GNU sed extension - it's not supported in every sed. It has to be removed, refactored, or you have to install GNU sed.

Overall, write it in awk, python or perl.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
2

Here is an Awk refactoring.

awk '/1/ { sub("1", "replaced-it", $0); replaced=1 } 1
    END { exit 1-replaced }' file.txt

Notice also how the cat is useless (with sed too, and generally any standard Unix command except annoyingly tr).

tripleee
  • 175,061
  • 34
  • 275
  • 318
1

An AWK equivalent would be:

awk '!sub(/1/,"replaced-it") {print; exit 1} 1' file.txt

If a substitution is not made successfully: print and exit with a status of 1; otherwise print.