0

I have a string with the structure task_name-student_name and I want to split it into two variables:

  • task: containing the chunk before the -
  • student: containing the chunk after the -

I can get this to work with sed:

string="task_name-student_name"
student=$(echo "$string" | sed "s/.*-//")
task=$(echo "$string" | sed "s/-[^-]*$//")

However, VS Code suggests "See if you can use $(variable//search/replace) instead".

So I have two questions:

  1. Why would $(variable//search/replace) be better
  2. How do I get the parameter expansion to work without it being interpreted as a command?

When I try

echo $("$string"//-[^-]*$//)

or

echo $(echo $("$string"//-[^-]*$//))

I get this output:

bash: task_name-student_name//-[^-]*$//: No such file or directory

Thanks in advance!

James Newton
  • 6,623
  • 8
  • 49
  • 113
  • 2
    See: `echo "${string#*-} and ${string%-*}"` and [Parameter Expansion](http://tiswww.case.edu/php/chet/bash/bashref.html#Shell-Parameter-Expansion) – Cyrus Jun 26 '21 at 09:00
  • `$( )` would not work.`${string/substring/replace}` could do simple replace but not support regex.I suggest use `IFS='-';read -a str_arr <<< "$string"` – nay Jun 26 '21 at 09:03

1 Answers1

5

First: for variable expansion, you want curly braces instead of parentheses. $(something) will execute something as a command; ${something} will expand something as a variable. And just for completeness, $((something)) will evaluate something as an arithmetic expression (integers only, no floating point).

As for replacing the sed with a variable expansion: I wouldn't use $(variable//search/replace} for this; there are more appropriate modifications. ${variable#pattern} will remove the shortest possible match of pattern from the beginning of the variable's value, so use that with the pattern *- to remove through the first "-":

student=${string#*-}

Similarly, ${variable%pattern} will remove from the end of the variable's value, so you can use this with the pattern -* to remove from the dash to the end:

task=${string%-*}

Note that the patterns used here are "glob" expressions (like filename wildcards), not regular expressions like sed uses; they're just different enough to be confusing. Also, the way I've written these assumes there's exactly one "-" in the string; if there's a possibility some student will have a hyphenated name or something like that, you may need to modify them.

There are lots more modifications you can do in a parameter expansion; see the bash hacker's wiki on the subject. Some of these modifications will work in other shells besides bash; the # and % modifiers (and the "greedy" versions, ## and %%) will work in any shell that conforms to the POSIX standard.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151