ChatGPT解决这个技术问题 Extra ChatGPT

sed error: "invalid reference \1 on `s' command's RHS"

I run several substitution commands as the core of a colorize script for maven. One of the sed commands uses a regular expression which works find in the shell as discussed here. The current (not working) implementation can be found here.

When I include one of the variants of the command into the script different behavior occurs:

Variant 1:

$ sed -re "s/([a-zA-Z0-9./\\ :-]+)/\1/g"

Adapted to the script:

-re "s/WARNING: ([a-zA-Z0-9./\\ :-]+)/${warn}WARNING: \1${c_end}/g" \

Error: The shell outputs the same information as if I would type $ sed. Strange!?

Variant 2:

$ sed -e "s/\([a-zA-Z0-9./\\ :-]\+\)/\1/g"

Adapted to the script:

-e "s/WARNING: \([a-zA-Z0-9./\\ :-]\+\)/${warn}WARNING: \1${c_end}/g" \

Error:

sed: -e expression #7, char 59: invalid reference \1 on `s' command's RHS

In my case I had combined a -i (edit in place option) with -re, resulting in -ire (so that -i was consuming the re fragment as its SUFFIX argument and hence the extended regex mode was not being enabled); changing it to -i -re fixed the issue.
It's also to notice that single quotes ' and double quotes " are treated slightly different, especially when interpreting $vars. For example: sudo sh -c "sed -r -i 's/(^.+_supplicant.conf)/\1${MTXT}/' /etc/network/interfaces" works, but: sudo sh -c 'sed -r -i "s/(^.+_supplicant.conf)/\1${MTXT}/" /etc/network/interfaces' does not.

S
SebMa

Don't you need to actually capture for that to work? i.e. for variant #2:

-r -e "s/WARNING: (\([a-zA-Z0-9./\\ :-]\+\))/${warn}WARNING: \1${c_end}/g" \

(Note: untested)

Without the -r argument back-references (like \1) won't work unless each parenthesis is escaped with a \ character.

With -r, argument back-references (like \1) won't work unless the parenthesis are NOT escaped.


The -r option to sed appears to be necessary for the back-reference to work. E.g sed -e 's/([[:digit:]])/is a digit/' works but sed -e 's/([[:digit:]])/\1 is a digit/ produces the original error without -r to sed. NOTE: the first invocation of sed searches for a literal (<digit>) and is not a capture group.
The comment below the answer is actually an answer. Maybe you can edit your answer to reflect it.
@AndrewFalanga you should have posted your comment as an answer
Nevermind my mistake was to use -ire instead of use -ri. Order matters :-)
-r, --regexp-extended = use extended regular expressions in the script. In most current versions the -E and -r both can be used. Extended as opposed to basic.
D
Dave Jarvis

This error is common for parentheses that are not escaped. Escape them and try again.

For example:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n(.)/\1/g

Should be escaped with backslashes before each parenthesis:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g

Attention, if you use -r you don't have to escape the parentheses.
O
OrangeDog

If the -r/--regexp-extended option is not provided, then the capturing parentheses must be escaped.


A
AndyG

You need escape the / after the .

sed -e "s/\([a-zA-Z0-9.\/\\ :-]\+\)/\1/g"

Or if you don't want to worry about escaping, use |

sed -e "s|\([a-zA-Z0-9./\\ :-]\+\)|\1|g"

EDIT:

sed -e "s|WARNING: \([a-zA-Z0-9.-/\\ :]+\)|${warn}WARNING: \1${c_end}|g"

Sound reasonable. But it does not work in the context of the script.
Sorry. The edit raises the error: sed: -e expression #7, char 58: Invalid range end. @Denis' answer works.
Ok, then +1 for @Denis' answer

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now