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

时间:2017-05-30 17:01:22

标签: bash shell

您好我将字符串例如/bin/bash/Xorg.tar.gz传递给我的脚本

    for i in $*; do 
       echo "$(expr match "$i" '\.*\.')"
     done

我希望只返回Xorg,但它返回0,任何想法为什么?

3 个答案:

答案 0 :(得分:1)

expr match指令尝试匹配完整输入而不是部分输入。

但是,你可以使用内置的BASH正则表达式:

[[ "$i" =~ .*/([^./]+)\. ]] && echo "${BASH_REMATCH[1]}"

这将为您的示例参数打印Xorg

答案 1 :(得分:1)

你的字符串 SQLContext sqlContext = new SQLContext(sc); DataFrame df = sqlContext.read() .format("com.databricks.spark.csv") .option("inferSchema", "true") .option("header", "true") .option("parserLib","univocity") .load("data.csv"); 似乎很奇怪(有点看起来像/bin/bash/Xorg.tar.gz是一个目录或其他东西)但无论如何,你可以使用标准参数扩展来获得你想要的部分:

/bin/bash

首先删除上一个i=${i##*/} i=${i%%.*} 之前的所有内容,然后删除第一个/中的所有内容。

答案 2 :(得分:1)

立即修复(将循环放在一边):

$ expr '/path/to/Xorg.tar.gz' : '.*/\([^.]*\)'
Xorg

注意:

    输入字符串后需要
  • :来表示正则表达式匹配操作。

    • 注意:expr <string> : <regex>是符合POSIX的语法; GNU expr也接受expr match <string> <regex>,与您的尝试一样。
  • expr隐式匹配字符串的 start ,因此必须使用.*/来匹配上一个/的所有内容

  • \([^.]*\)用于匹配文件名组件的第一个.以及但不包括的所有内容;请注意\ - ()(捕获组分隔符)的转义,这是必需的,因为expr仅支持(过时和有限){{3 }}秒。
    使用捕获组可确保输出匹配的字符串,而默认情况下输出匹配字符的计数。

  • 至于您使用的正则表达式

    • '\.*\.'\.*匹配文字 *字符的任何(可能为空)序列(.)。 (\.),隐含在字符串的开头,后跟正好1个字面.\.)。 换句话说:您尝试匹配2个或更多连续的 .个字符。 在字符串的开头,这显然不是你想要的。
    • 由于您的正则表达式不包含捕获组,expr会输出匹配字符的计数,在这种情况下为0,因为没有匹配。

那就是说,在shell循环的每次迭代中调用外部实用程序都是低效的,所以请考虑:

如果您实际上不需要shell循环并且可以使用外部实用程序使用单个命令处理所有路径,请考虑以下事项:

basename -a "$@" | cut -d'.' -f1

注意:basename -a,用于处理多个文件名操作数,是非标准的,但GNU和BSD / macOS basename都支持它。 < / p>

为了演示它的实际效果:

# 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