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

时间:2015-11-13 05:49:07

标签: string bash matching

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

[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 : '\(\[.*?\]\)'`

但是一旦我这样做,就不会返回任何内容

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

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

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

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

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

幸运的是,在这个孤立的案例中,获得非贪婪的匹配并不难。只需将正则表达式更改为方括号不匹配。

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

(结束方括号需要在否定字符类中首先出现;在任何其他位置,结束方括号关闭字符类。许多新手希望能够使用反斜杠转义,但这不是它的方式注意还添加了double quotes around the variable。)

答案 1 :(得分:1)

expr中正则表达式匹配不需要{p> bash

[[ $FOLDERNAME =~ (\[[^]]*\]) ]] && COMPANY=${BASH_REMATCH[1]}

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

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

答案 2 :(得分:0)

如果您对使用grep没有反感,那么:

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