提取由特殊符号界定的字符串的一部分



你好,我正在传递字符串,例如/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的语法; gnu expr也接受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

最新更新