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]}
}
我在目录中有文件夹,其名称提供了特定信息。例如:
[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]}
}