如何在bash中正确使用参数扩展

Jam*_*ton 0 bash parameter-expansion

我有一个带有结构的字符串task_name-student_name,我想将它分成两个变量:

  • task:包含之前的块-
  • student:包含后面的块-

我可以让它工作sed

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

然而,VS Code 建议“看看是否可以使用 $(variable//search/replace) 代替”。

所以我有两个问题:

  1. 为什么会$(variable//search/replace)更好
  2. 如何使参数扩展正常工作而不将其解释为命令?

当我尝试时

echo $("$string"//-[^-]*$//)
Run Code Online (Sandbox Code Playgroud)

或者

echo $(echo $("$string"//-[^-]*$//))
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

bash: task_name-student_name//-[^-]*$//: No such file or directory
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Gor*_*son 6

第一:对于变量扩展,您需要花括号而不是圆括号。$(something)something作为命令执行;${something}将扩展something为变量。为了完整起见,$((something))将计算something为算术表达式(仅整数,无浮点)。

至于用sed变量扩展替换:我不会用$(variable//search/replace}它;还有更合适的修改。将从变量值的开头${variable#pattern}删除最短的可能匹配,因此将其与模式一起使用以删除第一个“-”:pattern*-

student=${string#*-}
Run Code Online (Sandbox Code Playgroud)

同样,将从变量值的末尾${variable%pattern}删除,因此您可以将其与模式一起使用以从破折号删除到末尾:-*

task=${string%-*}
Run Code Online (Sandbox Code Playgroud)

请注意,这里使用的模式是“glob”表达式(如文件名通配符),而不是像seduses这样的正则表达式;它们的不同之处足以令人困惑。另外,我编写这些内容的方式假设字符串中只有一个“-”;如果某些学生的姓名可能带有连字符或类似内容,您可能需要对其进行修改。

您可以在参数扩展中进行更多修改;请参阅bash hacker 的 wiki 关于该主题的内容。其中一些修改可以在 bash 之外的其他 shell 中运行;和修饰符(以及“贪婪”版本和)将在任何符合 POSIX 标准的 shell 中工作#%##%%