0

I am using sed to keep only a single colon at the start of a string.

string=$( printf "%s\n" "$string" | sed 's/^::*/:/' )

Could this be done in bash using something like

[[ $string =~ regex ]]

with a regex group that will contain the parts of the string as required ?

Dilna
  • 405
  • 1
  • 6
  • 2
    It can be done with Bash extended globbing: `shopt -s extglob; string=${string/#+(:)/:}`. See the [extglob](https://mywiki.wooledge.org/glob#extglob) section in [glob - Greg's Wiki](https://mywiki.wooledge.org/glob). – pjh May 09 '23 at 21:40
  • I know about that one, the extended globbing. Would it be possible to enable it inside a bash function only. There has been a discussion recently about whether to allow extended globbing across a bash library. But the difficulty is that some need extglob off If they wish a firm guarantee that scripts written assuming POSIX behavior will still conform to the standard. What do you think ? – Dilna May 09 '23 at 22:01
  • Enable the glob inside the function? – Jetchisel May 09 '23 at 22:14
  • @Jetchisel extglob should have a global scope due to the way bash evaluates blocks – Sir Athos May 09 '23 at 22:18
  • 1
    With bash regex, how about `[[ $string =~ ^:+(.*) ]] && string=":${BASH_REMATCH[1]}"`? – tshiono May 09 '23 at 22:19
  • @SirAthos. Ok, and if you disable `extglob` at the end of the function? – Jetchisel May 09 '23 at 22:20
  • `regex='^(:{1,})(.*)$';string=:::::::::string:; [[ "$string" =~ $regex ]]; declare -p BASH_REMATCH` – Jetchisel May 09 '23 at 22:21
  • @Jetchisel I think the requirement here is rather, as a library, not to touch the extglob setting at all. – Sir Athos May 09 '23 at 22:24
  • Well POSIX, is all about external tools, so yeah, `sed` or `awk` . – Jetchisel May 09 '23 at 22:27
  • That question was asked before by the same user: https://stackoverflow.com/questions/76194470/ensuring-a-single-colon-at-start-of-string – Jetchisel May 09 '23 at 22:40
  • Yes, a similar question was asked before but this starts with the sed example and mentions that extended globbing could not be suitable for some users. – Dilna May 09 '23 at 22:48
  • There should be no problem having `extglob` enabled globally. It's very unlikely to cause problems for code that doesn't use extended globbing. Bash can be built with `extglob` enabled by default, and I've worked on Linux distros where the standard Bash installation had been built in that way. See [Is it dangerous to always have extglob on?](https://unix.stackexchange.com/q/276911/264812). – pjh May 10 '23 at 00:18
  • It makes sense for a *library* function that depends on extended globbing to turn on `extglob` and turn it off again if necessary. One way to do that is `local is_changed_extglob=1; shopt -q extglob && is_changed_extglob=0 || shopt -s extglob; ...; (( is_changed_extglob )) && shopt -u extglob`. – pjh May 10 '23 at 00:33

1 Answers1

0

With any posix shell:

# ensure exactly one colon
string=:${string#${string%%[!:]*}}

# ensure no more than one colon
case $string in :*) string=:${string#${string%%[!:]*}};; esac

Using BASH_REMATCH:

# ensure exactly one colon
[[ $string =~ ^:*(.*)$ ]]
string=:${BASH_REMATCH[1]}

# ensure no more than one colon
[[ $string =~ ^(:?):*(.*)$ ]]
string=${BASH_REMATCH[1]}${BASH_REMATCH[2]}
jhnc
  • 11,310
  • 1
  • 9
  • 26
  • I had not noticed before answering that this was a duplicate question with the same posix part of the answer already at https://stackoverflow.com/a/76195107/10971581 – jhnc May 10 '23 at 02:15