你好,我正在传递字符串,例如/bin/bash/xorg.tar.gz到我的脚本
for i in $*; do
echo "$(expr match "$i" '.*.')"
done
我希望只返回Xorg,但它返回0,有什么想法为什么?
您的字符串将是/bin/bash/Xorg.tar.gz
(Kinda看起来像/bin/bash
是目录或其他内容(,但是无论哪种方式,您都可以使用标准参数扩展来获取所需的零件:
i=${i##*/}
i=${i%%.*}
首先将所有内容删除到最后一个/
,然后删除第一个.
中的所有内容。
expr match
指令尝试匹配完整输入而不是部分。
但是,您可以使用内置的bash Regex为此:
[[ "$i" =~ .*/([^./]+). ]] && echo "${BASH_REMATCH[1]}"
这将为您的示例参数打印Xorg
。
立即 fix (将环留一旁(:
$ expr '/path/to/Xorg.tar.gz' : '.*/([^.]*)'
Xorg
注意:
在输入字符串之后需要
:
来发出 REGEX匹配操作。- 注意:
expr <string> : <regex>
是符合POSIX的语法; gnuexpr
也接受expr match <string> <regex>
,就像您的尝试一样。
- 注意:
expr
隐式匹配字符串的 start ,因此必须使用.*/
将所有内容匹配到最后一个/
([^.]*)
用于将所有内容与文件名组件的第一个.
匹配;请注意需要(
和)
的-esscaping(捕获组定界符(,因为
expr
仅支持(过时的和有限的(BRES。
使用捕获组确保输出匹配的字符串,而默认情况下,匹配字符的计数是输出的。是输出。至于您使用的正则:
-
'.*.'
:.*
匹配字面.
chars的任何(可能为空(序列(*
(。(.
(,隐式在字符串开始时,然后是1个字面的.
(.
(。
换句话说:您尝试匹配2个或更多连续.
字符。在字符串的开头,这显然不是您的意图。 - 因为您的正则言论不包含捕获组,因此
expr
输出匹配字符的计数,在这种情况下为0
,因为没有任何匹配。
-
也就
Tom Fenech的有用答案,仅使用 shell参数扩展。
Anubhava的有用答案,该答案仅使用Bash的内置正则匹配操作员
=~
如果您实际上不需要shell loop ,并且使用外部实用程序使用进行处理所有路径,请考虑以下内容:
basename -a "$@" | cut -d'.' -f1
注意:basename -a
,用于处理多个文件名操作数,但GNU和BSD/MACOS basename
都支持它。
在行动中演示它:
# Set positional parameters with `set`.
$ set -- '/path/to/Xorg.tar.gz' '/path/to/another/File.with.multiple.suffixes'
$ basename -a "$@" | cut -d'.' -f1
Xorg
File