Bash 如何从文件名中提取段?

Bash 如何从文件名中提取段?,bash,shell,Bash,Shell,我有一个具有以下命名方案的文件目录: <project name>-<group name>.txt 如何做到这一点?我正在试验${f###…}和${f%…},但迄今为止没有成功。我不确定它们是否可以组合在一起,因此我可以先省略前缀-,然后再省略后缀.txt我不知道是否可以在一行中实现,但如果按步骤进行,则很容易: for f in *.txt; do base=${f%.txt} projectname=${base%-*} groupname

我有一个具有以下命名方案的文件目录:

<project name>-<group name>.txt

如何做到这一点?我正在试验
${f###…}
${f%…}
,但迄今为止没有成功。我不确定它们是否可以组合在一起,因此我可以先省略前缀
-
,然后再省略后缀
.txt

我不知道是否可以在一行中实现,但如果按步骤进行,则很容易:

for f in *.txt; do
    base=${f%.txt}
    projectname=${base%-*}
    groupname=${base#*-}
    echo project name: $projectname
    echo group name: $groupname
done
如果您可以调用外部程序,那么这也可以工作,并且可读性很好

for f in *.txt; do
    groupname=$(basename ${f#*-} .txt)
    echo group name: $groupname
done

分步做很聪明,很好,谢谢。如果这可以写成一行,那就太棒了,因为我只需要组名。@Bradson如果你使用zsh,你可以嵌套它们:
groupname=${${f%-*}%.sql}
,但是bash不支持这个。谢谢,我没有意识到。改成
/bin/bash
我不知道关于
bash\u重新匹配的事,但这正是我需要的。谢谢您的回答。@PesaThe
bash
可执行文件并不总是在
/bin
中。使用
#之类的东西通常更便于移植/usr/bin/env bash
。(不使用bashism也更具可移植性,但由于避免使用bashism比在每个脚本中多键入8个字符更难,因此它们通常是值得的)。
for f in *.txt; do
    groupname=$(basename ${f#*-} .txt)
    echo group name: $groupname
done
for file in *-*.txt; do
    # shortest match: a-b-c-d.txt => d
    [[ $file =~ ([^-]+).txt$ ]] && echo "${BASH_REMATCH[1]}"
    # longest match: a-b-c-d.txt => b-c-d
    [[ $file =~ -(.+).txt$ ]] && echo "${BASH_REMATCH[1]}"
done