【问题标题】:How to use parameter expansion correctly in bash [duplicate]如何在bash中正确使用参数扩展[重复]
【发布时间】:2021-06-26 08:45:48
【问题描述】:

我有一个结构为task_name-student_name 的字符串,我想将其拆分为两个变量:

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

我可以使用sed:

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

但是,VS Code 建议“看看你是否可以改用 $(variable//search/replace)”。

所以我有两个问题:

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

当我尝试时

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

或

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

我得到这个输出:

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

提前致谢!

【问题讨论】:

  • 见:echo "${string#*-} and ${string%-*}" 和 Parameter Expansion
  • $( ) 不起作用。${string/substring/replace} 可以做简单的替换但不支持正则表达式。我建议使用IFS='-';read -a str_arr <<< "$string"

标签: bash parameter-expansion


【解决方案1】:

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

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

student=${string#*-}

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

task=${string%-*}

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

您可以在参数扩展中进行更多修改;见bash hacker's wiki on the subject。其中一些修改将在 bash 之外的其他 shell 中工作; # 和 % 修饰符(以及“贪婪”版本,## 和 %%)可以在任何符合 POSIX 标准的 shell 中工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2019-08-02
    • 2017-01-27
    • 1970-01-01
    相关资源
    最近更新 更多