BASH 匹配字符串开头的 glob 的脚本

BASH script matching a glob at the begining of a string

我在目录中有文件夹,其名称提供了特定信息。例如:

[allied]_remarkable_points_[treatment]

[nexus]_advisory_plans_[inspection]

....

所以我有一个类似这样的结构:[company]_title_[topic]。脚本必须将文件命名结构与脚本中的变量相匹配才能提取信息:

COMPANY='[allied]';
TITLE='remarkable points'
TOPIC='[treatment]'

文件夹不包含固定数量的字符,所以我不能在脚本中使用索引匹配。我设法提取了 $TITLE$TOPIC,但我无法匹配第一个字符串,因为该变量使我返回了完整的文件夹名称。

FOLDERNAME=${PWD##*/}

这是让我悲伤的台词:

COMPANY=`expr $FOLDERNAME : '\(\[.*\]\)'`

我试图通过放置 ?在正则表达式中:

COMPANY=`expr $FOLDERNAME : '\(\[.*?\]\)'`

但是一旦我这样做,returns 什么都没有

有什么想法吗?

如果您不反对使用 grep,那么:

COMPANY=$(grep -Po "^\[.*?\]" $FOLDERNAME)

Bash 具有内置的字符串操作功能。

for f in *; do
    company=${f%%\]*}
    company=${company#\[}  # strip off leading [
    topic=${f##\[}
    topic=${f%\]}          # strip off trailing ]
    :
done

构造 ${variable#wildcard}variable 的值和 returns 的结果字符串中删除任何匹配 wildcard 的前缀。加倍 # 获得最长的可能通配符匹配而不是最短的。使用 % 选择后缀而不是前缀替换。

如果出于某种原因您确实想使用 expr,您的非贪婪正则表达式尝试不起作用的原因是此语法比任何与 expr 相关的语法都要新得多。事实上,如果您正在使用 Bash,您可能根本不应该使用 expr,因为 Bash 为 expr 的每个用例提供了卓越的内置功能从某种意义上说,在遥远的过去,sh shell 没有内置的正则表达式匹配和算术。

幸运的是,在这种孤立的情况下,不难获得非贪婪匹配。只需将正则表达式更改为不匹配方括号即可。

COMPANY=`expr "$FOLDERNAME" : '\(\[[^][]*\]\)'`

(在否定字符 class 中,右方括号需要先出现;在任何其他位置,右方括号将字符 class 闭合。许多新手希望能够使用反斜杠为此进行了转义,但这不是它的工作原理。另请注意 double quotes around the variable.)

expr 不需要 bash.

中的正则表达式匹配
[[ $FOLDERNAME =~ (\[[^]]*\]) ]] && COMPANY=${BASH_REMATCH[1]}

使用 [^]]* 而不是 .* 对括号部分进行非贪婪匹配。更大的正则表达式可以捕获所有三个部分:

[[ $FOLDERNAME =~ (\[[^]]*\])_([^_]*)_(\[[^]]*\]) ]] && {
    COMPANY=${BASH_REMATCH[1]}
    TITLE=${BASH_REMATCH[2]}
    TOPIC=${BASH_REMATCH[3]}
}