【问题标题】:Could not extract jdk-version using grep-command and regular expressions无法使用 grep-command 和正则表达式提取 jdk-version
【发布时间】:2021-03-11 14:42:54
【问题描述】:

我正在尝试使用regular-expressions 提取jdk 的版本实际上我有以下版本:

openjdk 11.0.9.1 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-Ubuntu-0ubuntu1.18.04)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-Ubuntu-0ubuntu1.18.04, mixed mode,sharing)

我写了正则表达式。它如下所示: ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}$

此正则表达式正在在线正则表达式测试器上运行 (https://regex101.com/)。不幸的是,它不适用于 grep-command。我正在使用扩展正则表达式。我的 jdk-version 提取代码如下所示:

CMD_RESULT=$(java --version 2>&1 | head -n 1 | cut -d '' -f 2)
if [ ! -z "$CMD_RESULT" ]
then 
    for token in $CMD_RESULT
    do
       JAVA_VERSION=$(echo $token |  grep -e $VERSION_EXTRACTION_REGEX)
       if [ ! -z  $JAVA_VERSION ];
       then
            printf "${GREEN}Java version: [$JAVA_VERSION]\n"
       fi
     done
fi

我不明白,为什么我的正则表达式正在在线正则表达式检查器上工作,而它却不能与 grep 命令一起工作。我将参数 -e 用于扩展正则表达式。

有什么想法吗?

【问题讨论】:

  • 欢迎来到 SO,很高兴你在你的问题中展示了你的尝试,继续努力。您能否使用代码标签在您的问题中发布java --version 命令的输出,以便更好地理解您的问题。
  • 您的正则表达式完全错误; ^ 匹配行首,$ 匹配行尾,其间的所有内容仅限于数字 ([0-9]) 和点 (\.)。此外,grep -e 不足以支持此正则表达式,因此您可能必须使用扩展 (grep -E)。
  • 为了清楚起见,您能否在问题中提及预期输出示例,您要打印哪一行的版本,请在您的问题中明确提及。

标签: regex bash awk


【解决方案1】:

对 OP 当前代码的一些小改动:

  • 在cmets中提到,^$代表输入的开始和结束;从正则表达式中删除这些
  • 虽然grep 可以使用生成的正则表达式,但有必要告诉grep-Extended 正则表达式模式下运行
  • 我们可以使用grep's-o 选项将输出限制为仅匹配正则表达式的部分

示例输入数据:

$ cat jdk.dat
openjdk 11.0.9.1 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-Ubuntu-0ubuntu1.18.04)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-Ubuntu-0ubuntu1.18.04, mixed mode,sharing)

一个使用 OP 修改的正则表达式的grep 解决方案:

$ grep -oE '[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}' jdk.dat
11.0.9.1
11.0.9.1
11.0.9.1

同样的事情,但正则表达式存储在 OPs 变量中:

$ VERSION_EXTRACTION_REGEX='[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}'
$ grep -oE "${VERSION_EXTRACTION_REGEX}" jdk.dat
11.0.9.1
11.0.9.1
11.0.9.1

注意:我将由用户决定使用哪个值,例如,head -n 1 仅使用第一行输入 (openjdk 11.0.9.1 2020-11-04)

【讨论】:

  • 呃,我认为你的意思是相反的; awk 可以(大致)处理 ERE 语法,而普通的 grep 不能,并且需要 -E 才能启用支持。
  • 更像... arg ... 在几个不同的答案之间跳跃;已更新以将 awk 引用替换为 grep;并感谢您的编辑(也许我应该暂时离开键盘......)
【解决方案2】:

只使用本机 Bash 命令来解析 java 版本字符串:

#!/usr/bin/env bash

# Capture java command path if it exists OR exit fail
java_cmd=$(command -v java) || exit 1

# Capture java raw version output
java_raw_version=$("$java_cmd" -version 2>&1)

# Match java raw version string against Bash Regex OR dump debug if match fail
[[ $java_raw_version =~ ([0-9]+)\.([0-9]+)\.([0-9]+)[_.+-]([0-9]+) ]] ||
  typeset -p java_raw_version BASH_REMATCH

major=${BASH_REMATCH[1]}   # Regex capture group 1
minor=${BASH_REMATCH[2]}   # Regex capture group 2
patch=${BASH_REMATCH[3]}   # Regex capture group 3
release=${BASH_REMATCH[4]} # Regex capture group 4

# Recompose a semantic version string
semver="$major.$minor.$patch-$release"

printf 'Java semantic version is: %s\n' "$semver"

示例输出:

发件人:

openjdk version "1.8.0_275"
OpenJDK Runtime Environment (build 1.8.0_275-8u275-b01-0ubuntu1~20.10-b01)
OpenJDK 64-Bit Server VM (build 25.275-b01, mixed mode)

输出:

Java semantic version is: 1.8.0-275

发件人:

openjdk 11.0.9.1 2020-11-04
OpenJDK Runtime Environment (build 11.0.9.1+1-Ubuntu-0ubuntu1.18.04)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-Ubuntu-0ubuntu1.18.04, mixed mode,sharing)

输出:

Java semantic version is: 11.0.9-1

关于语义版本控制,请参阅:https://semver.org/

【讨论】:

    【解决方案3】:

    这里有一个非常简单的awk解决方案(不需要regexp):

    #!/usr/bin/env bash
    
    # Capture java command path if it exists OR exit fail
    java_cmd=$(command -v java) || exit 1
    
    # Capture java raw version output
    java_raw_version=$("$java_cmd" -version 2>&1)
    
    # print out the Java version:
    echo $java_raw_version | awk -F \" 'NR==1{print "Java semantic version is: "$2}''
    

    说明:

    -F \" 将 awk 字段分隔符设置为 "

    NR==1 只处理#1 行

    print "Java semantic version is: "$2 将第二个字段附加到文本并打印

    【讨论】:

    • 获取不是语义版本的Java semantic version is: 1.8.0_275。而且您不需要捕获变量然后回显缺少引号的变量。我很高兴您从我的回答中找到了灵感,但是如果做得不好,会令人失望。使用java -version 2>&1 | awk -F \" 'NR==1{split($2,ver,/[_.+-]/); printf("Semantic version: %s.%s.%s-%s\n",ver[1],ver[2],ver[3],ver[4])}' 你会更有创意
    • 当你什么都不用的时候,为什么还需要捕获路径呢?
    猜你喜欢
    • 1970-01-01
    • 2015-11-11
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    相关资源
    最近更新 更多