1

UPD guys, the above statement "This question already has an answer here: <link>" is just plain wrong: there is no answer there. I know about sed, but this is not an option. It looks like this is just not possible. Not in bash, not in a one-liner, not in 2018.

The bash string substitution supports regular expressions, but I cannot find a way to include a part of the matched string into the replacement.

The following does not do what I want:

$ x=AbcdAbdcAbefAbfe
$ echo ${x//Ab[ef]/Zy\\1}
AbcdAbdcZy\1fZy\1e
$ echo ${x//Ab[ef]/AB\1}
AbcdAbdcAB1fAB1e

(well, in fact, I cannot even use parens:

$ echo ${x//Ab/Zy}
ZycdZydcZyefZyfe
$ echo ${x//(Ab)/Zy}
AbcdAbdcAbefAbfe

)

What I want may be achieved via a series of substitutions:

$ x=AbcdAbdcAbefAbfe
$ t="$x"
$ t=${t//Abe/Zye}
$ t=${t//Abf/Zyf}
$ echo $t
AbcdAbdcZyefZyfe

but even for [0-9] it becomes a long story.

The code runs in a long loop, it should be a one-liner that does not launch sub-processes.

EDIT

There is an answer in the comments. I copy it here:

this was not a question about regular expressions, and that assumption in the question was incorrect. The initial sentence in the question posits something that is false. The pattern in a parameter expansion is treated as a glob. – ghoti

You should have probably linked to this directly. That page elaborates on everything needed to put an end to this discussion. – revo

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • What makes you think that bash parameter expansion supports regular expressions? – ghoti Nov 02 '18 at 19:57
  • see also [Unix.SE: Does bash support back references in parameter expansion?](https://unix.stackexchange.com/q/361134/254446) – The Guy with The Hat Nov 02 '18 at 19:58
  • @ghoti As I read from [tldp](http://tldp.org/LDP/abs/html/refcards.html#AEN22828) *`${string//substring/replacement}` where $substring is a Regular Expression.* – revo Nov 02 '18 at 20:32
  • @ghoti see my 1st example. That output is possible only if regex-es are supported. – 18446744073709551615 Nov 02 '18 at 21:36
  • @18446744073709551615, are you saying that your example which didn't work made you think that a feature existed that does not exist? :-D [Here](https://unix.stackexchange.com/a/46444/13377) is how I addressed this one time in the past. Ranges are not exclusive to regular expressions. – ghoti Nov 02 '18 at 22:29
  • @revo That TLDP page is really hard to parse. Only the `expr` forms support regular expressions, so only the `expr` forms have the asterisk referencing the footnote about regular expressions. All of the `${string/...}` forms use glob patterns instead (and don't have the asterisk). – Gordon Davisson Nov 03 '18 at 01:32
  • @revo, I generally don't recommend relying on TLDP. If you're looking at "Table B-5" on that page, it doesn't mention regexes, it mentions substrings .. which is also incorrect, as the thing we're talking about in `${parameter/pattern/string}` is a *pattern*, not just a substring. The note at the bottom of the table refers to lines with an asterisk, i.e. `expr "$string" : regex`. But that whole page is badly written and misleading. Read the bash man page first, and [the official docs](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html). – ghoti Nov 03 '18 at 03:20
  • @ghoti So is this an extension `STR="...." && echo ${STR//[^[:space:]]/X}` ? – revo Nov 03 '18 at 05:41
  • @revo, what are you asking? That pattern will match any character that isn't a space. [`man isspace`](http://man.freebsd.org/isspace) to see how that class works. – ghoti Nov 03 '18 at 17:13
  • @ghoti That's a negated POSIX character class defined in POSIX regular expressions. I'm asking if it isn't regex then what is it? – revo Nov 03 '18 at 17:40
  • @revo, it's a POSIX character class, negated by a bracket expression. Character classes are not exclusive to regular expressions. The class is implemented as a function in libc, and is used to recognize characters. Regular expressions use them. Globs use them. They're a consistent, reliable, portable toolset that C programmers can (and do) implement all over the place. If you need a locale-sensitive way of determining how to classify input, you use character classes. – ghoti Nov 04 '18 at 04:25
  • @ghoti You should have probably linked to [this](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching) directly. That page elaborates on everything needed to put an end to this discussion. Thanks anyway. – revo Nov 04 '18 at 06:16
  • @revo, this question was about parameter expansion. You asked about pattern matching in comments. Perhaps you should have [asked a question](https://stackoverflow.com/questions/ask) yourself if you needed help with this. – ghoti Nov 04 '18 at 12:36
  • @ghoti I didn't feel to have need for help and this question was about regular expressions in bash string substitution and we were talking about it all the time. – revo Nov 04 '18 at 13:01
  • @revo, alas, this was not a question about regular expressions, and that assumption in the question was incorrect. The initial sentence in the question posits something that is false. The pattern in a parameter expansion is treated as a glob. – ghoti Nov 04 '18 at 13:46
  • @ghoti Yes. The only reason I decided to have you to shed some light on this was that wrong assumption in the question and my own uncertainties. – revo Nov 04 '18 at 13:57
  • @revo on my ubuntu `STR="...." && echo ${STR//[^[:space:]]/X}` outputs `XXXX` – 18446744073709551615 Nov 07 '18 at 09:27
  • @ghoti is there any way to have look-ahead or look-behind functionality in glob, or a way to have ${param/pattern/string} use regex instead of glob? – 18446744073709551615 Nov 07 '18 at 09:45

0 Answers0