需要从包含分隔符的文件路径字符串中提取子字符串

需要从包含分隔符的文件路径字符串中提取子字符串

在执行 shell 脚本时,输入的字符串类似于:

test1/test2/Test.jar/Test2.jar/com/test/ui/GI.class

我怎样才能提取: test1/test2/Test.jar[即子字符串直到第一次出现'.jar'分隔符,包括在内],在shell脚本中

我该怎么做?我不想使用 cut 然后在末尾附加“.jar”。

谢谢

答案1

除了sed,您还可以选择使用grep为此,使用 PCRE 正则表达式^.*?\.jar

grep -oP '^.*?\.jar' <<<"test1/test2/Test.jar/Test2.jar/com/test/ui/GI.class"

这只打印匹配项 ( -o),使用聚合酶链反应( -P),匹配以下文本:

  • 从行首开始 ( ^),并且
  • 包含任意字符 ( .),任意次数但延迟匹配 ( *?),
  • 后跟文字.字符 ( \.) 和jar( jar)

使用惰性量词 *?而不是通常的贪婪量词*导致grep匹配尽可能少的字符。

  • 如果没有它(而是使用贪婪量词),grep只要匹配以 结尾,就会匹配尽可能多的字符.jar,这将在匹配之后无法停止第一的 .jar在存在多个的情况下。
  • -P标志是必需的,因为grepUbuntu 支持的正则表达式方言,PCRE 是支持惰性的。 (这种方言非常类似于Perl 中的正则表达式方言

答案2

您可以sed像下面这样使用:

sed 's/\(\.jar\).*/\1/' <<<"test1/test2/Test.jar/Test2.jar/com/test/ui/GI.class" 

或者通过awk命令:

awk -F'\\.jar' '{print $1".jar"}' <<<"test1/test2/Test.jar/Test2.jar/com/test/ui/GI.class"

输出为:

test1/test2/Test.jar

答案3

既然您提到了 shell 脚本,我提出一个简单的、纯基于 shell 的解决方案:

s='test1/test2/Test.jar/Test2.jar/com/test/ui/GI.class'
echo "${s%%.jar*}.jar"

参数扩展 %%删除最长后缀与后续匹配全局模式 .jar*(与%匹配最短后缀相反)。

答案4

由于这个问题被标记为bash,这里有一个bash带有 C 风格循环和${variable:beginning:offset}参数扩展的脚本来提取单个字符

#!/usr/bin/env bash

substring=""
for ((i=0;i<=${#1};i++))
do
    substring="$substring""${1:$i:1}"
    if [[ "$substring" == *.jar ]]
    then
        echo "$substring"
        substring=""
    fi
done

实际操作如下:

$ ./parse_string.sh test1/test2/Test.jar/Test2.jar/com/test/ui/GI.class                                                                              
test1/test2/Test.jar
/Test2.jar

如果我们只想提取第一次出现的情况,请在内部语句break后添加一行substring=""if

相关内容