0

After reading some docs from globs in bash

https://mywiki.wooledge.org/glob#extglob

I´m struggling to replace a part of a variable:

Just an example that i am using to learn a bit more

myvar="value1=aaa value2=bbb value3=ccc value4=ddd"

value2="zzz"

myvar="${myvar//value2=*([a-z0-9-])/value2=${value2}}"

result:

echo $myvar
value1=aaa value2=zzz

expected result:

echo $myvar
value1=aaa value2=zzz value3=ccc value4=ddd

The result of the code above is not the expected one as it´s deleting everything behind value2=bbb in myvar.

If I use:

shopt -s extglob

it is working from a virtual machine with linux but from my current machine is not even if the begining of the script starts with #!/bin/bash. Most probably because i´m not using bash in my terminal.

Any other way to achieve this? (with sed for example without enabling extglob)

thx

X T
  • 445
  • 6
  • 22
  • What's the result you expect, and why do you expect it? – Charles Duffy May 09 '22 at 16:56
  • 1
    ...btw, the best way to store a list of key/value pairs in bash is with an associative array. – Charles Duffy May 09 '22 at 16:57
  • 2
    also, critically: **did you turn on extglobs in the shell you're running this in?** The meaning of `*([a-z0-9-])` is completely different in a shell where extglobs are off. – Charles Duffy May 09 '22 at 16:58
  • @CharlesDuffy i´ve already updated the expected result which is "echo $myvar value1=aaa value2=zzz value3=ccc value4=ddd". I tried to run this "shopt -s extglob". Looks like it is not recognized command. – X T May 09 '22 at 17:37
  • 2
    Your shell probably isn't `bash` if `shopt -s extglob` isn't recognized. – M. Nejat Aydin May 09 '22 at 17:52
  • i updated the question as i got shopt work in bash but the result is not the expected one. – X T May 09 '22 at 17:54
  • What is the output of this command: `shopt | grep extglob` ? – M. Nejat Aydin May 09 '22 at 17:58
  • Cannot reproduce: after the re-assignment, what does `declare -p myvar` show? – glenn jackman May 09 '22 at 18:02
  • Is there any way to do that without globs? – X T May 09 '22 at 18:03
  • I got to setup shopt -s extglob from a pipeline that use a linux machine. However, impossible to show that extglob i tried different ways including echo. I know that is setup because in other case pipeline will fail. My local terminal is OSX. – X T May 09 '22 at 18:35
  • 2
    If `shopt -s extglob` isn't working then you are not using Bash. Even the ancient Bash on macOS supports `extglob`. The login shell on macOS (I believe) is often not Bash, so you can't test Bash code at the command line with it. You need to either run the Bash program file explicitly with `bash` or give it a `bash` [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) line, make it executable (with `chmod`), and run it directly. – pjh May 09 '22 at 18:57
  • 1
    See [What are all options to execute and source a bash file? Why shebang is not checked?](https://stackoverflow.com/q/62747803/4154375). – pjh May 09 '22 at 18:57
  • I see. Basically i am using a virtual machine to test with Bash. That´s totally right in bash, after enabling "shopt -s extglob", it is working. However, looks like in my machine/pipeline i cannot use thet shopt...it´s omitting the shopt-s extglob (because as you said i am not using bash) is there any way to translet what i want to do with SED for example? – X T May 09 '22 at 19:28
  • Yes, plenty of ways to do what you want with sed, but that would be a completely different question (and also probably one already in our knowledge base already asked-and-answered). – Charles Duffy May 09 '22 at 20:11
  • 1
    Regarding "...not even if the begining of the script starts with #!/bin/bash. Most probably because i´m not using bash in my terminal.": if the script starts with `#! /bin/bash` and you are running it correctly (e.g. with `bash progname` or `./progname`) then it doesn't matter what shell is running in your terminal. See [What are all options to execute and source a bash file? Why shebang is not checked?](https://stackoverflow.com/q/62747803/4154375). – pjh May 09 '22 at 21:27
  • With sed -E 's/value2=*([a-z0-9-])/'"$myvar"'/g' the problem here is that I cannot redirect directly to a variable. It must be a file. However, I would not like to create any temp file for that. – X T May 09 '22 at 21:28
  • 1
    See [How do I set a variable to the output of a command in Bash?](https://stackoverflow.com/q/4651437/4154375) for details of how to capture `sed` output to a variable. (Ignore answers that suggest using the antiquated backticks though.) Note that your `sed` command won't work in its current form because you are using (extended) glob patterns and `sed` uses regular expressions. – pjh May 09 '22 at 21:40

1 Answers1

1

If you really can't use Bash, then you can maybe do what you want with lowest common denominator shell features like this:

pre=${myvar%%value2=*}
post=${myvar#"$pre"value2=}
v2=${post%%[!a-z0-9-]*}
post=${post#"$v2"}
myvar="${pre}value2=${value2}${post}"
pjh
  • 6,388
  • 2
  • 16
  • 17