bash中如何正确使用参数展开
How to use parameter expansion correctly in bash
我有一个结构为 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) 代替”。
所以我有两个问题:
- 为什么
$(variable//search/replace)
会更好
- 如何在不将其解释为命令的情况下使参数扩展起作用?
当我尝试时
echo $("$string"//-[^-]*$//)
或
echo $(echo $("$string"//-[^-]*$//))
我得到这个输出:
bash: task_name-student_name//-[^-]*$//: No such file or directory
提前致谢!
首先:对于变量扩展,你需要花括号而不是圆括号。 $(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; #
和 %
修饰符(以及“贪心”版本 ##
和 %%
)将在任何符合 [=45= 的 shell 中工作]标准。
我有一个结构为 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) 代替”。
所以我有两个问题:
- 为什么
$(variable//search/replace)
会更好 - 如何在不将其解释为命令的情况下使参数扩展起作用?
当我尝试时
echo $("$string"//-[^-]*$//)
或
echo $(echo $("$string"//-[^-]*$//))
我得到这个输出:
bash: task_name-student_name//-[^-]*$//: No such file or directory
提前致谢!
首先:对于变量扩展,你需要花括号而不是圆括号。 $(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; #
和 %
修饰符(以及“贪心”版本 ##
和 %%
)将在任何符合 [=45= 的 shell 中工作]标准。