1

伙计们,

我搜索了很多,但无法为我的问题找到理想的解决方案。所以我必须在这里发帖。

我需要从一个字符串中提取两个数字,该字符串可能包含也可能不包含其他数字,除了我要解析的这两个数字。

例如,字符串可能如下所示:

newSetupSL5_snolab_Int-300_Exp-10000_3515

snolab_Int-300_Exp-10000_1185

newSetupSL5_snolab_Int-300_Exp-5000_2522

所以,我要提取的是“Int-”和“Exp-”之后的数字,分别对应第一个和第二个字符串中的300和10000,第三个字符串中的300和5000。

此外,我需要使用这两个数字进行进一步分析。也就是说,我希望这两个数字可以分配给两个变量,而不是直接打印出来,用 bash 脚本,而不是命令行格式。

4

3 回答 3

4

使用 bash 正则表达式匹配

while read line; do
    if [[ $line =~ _Int-([[:digit:]]+)_Exp-([[:digit:]]+) ]]; then
        printf "int=%d; exp=%d\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
    fi
done <<END
newSetupSL5_snolab_Int-300_Exp-10000_3515
snolab_Int-300_Exp-10000_1185
newSetupSL5_snolab_Int-300_Exp-5000_2522
END
int=300; exp=10000
int=300; exp=10000
int=300; exp=5000

删除 while 循环

str=newSetupSL5_snolab_Int-300_Exp-10000_3515
if [[ $line =~ _Int-([[:digit:]]+)_Exp-([[:digit:]]+) ]]; then
    printf "int=%d; exp=%d\n" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
fi
于 2013-10-16T09:22:45.850 回答
2

grep可以用这个后视表达式来实现:

$ grep -Po '(?<=Int-)\d+|(?<=Exp-)\d+' file
300
10000
300
10000
300
5000

为了更清楚地看到它,请注意它是如何在 之后获取数字的Int-

$ grep -Po '(?<=Int-)\d+' file
300
300
300

然后只需将其他条件与|.


更新

Glenn Jackman 的伟大建议改进了输出:

$ grep -Po '(?<=Int-)\d+|(?<=Exp-)\d+' file | paste - - | while read n1 n2
> do
> echo "int=$n1 ext=$n2"
> done
int=300 ext=10000
int=300 ext=10000
int=300 ext=5000

关于OP的评论

@fedorqui 和 glenn jackman:非常感谢您的代码 - 您的代码看起来非常好。然而,正如我在原始消息中提到的,我实际上需要一行代码来处理一个字符串,而不是一个文件。并且此代码行应集成到我的脚本中。你知道如何用 "$string" 替换 "file" 吗?非常感谢 !

你可以这样做:

grep -Po '(?<=Int-)\d+|(?<=Exp-)\d+' <<< "$string"
于 2013-10-16T09:08:08.667 回答
0

下,有办法做到这一点,而无需外部工具(叉子),如sedawk或其他:

i=0;
while read string ;do
    ((i++))
    int=${string#*Int-}
    int=(${int//[a-z_-]/ })
    exp=${string#*Exp-}
    exp=(${exp//[a-z_-]/ })
    var=(${string//[a-z_-]/ })
    printf "Line #%2d contain: Int: %6s, Exp: %6s in %2d values: <%s>\n" \
        $i "$int" "$exp" ${#var[@]} "${var[*]}"
  done <<<'
newSetupSL5_snolab_Int-300_Exp-10000_3515

snolab_Int-300_Exp-10000_1185

newSetupSL5_snolab_Int-300_Exp-5000_2522
'
Line # 1 contain: Int:       , Exp:        in  0 values: <>
Line # 2 contain: Int:    300, Exp:  10000 in  4 values: <5 300 10000 3515>
Line # 3 contain: Int:       , Exp:        in  0 values: <>
Line # 4 contain: Int:    300, Exp:  10000 in  3 values: <300 10000 1185>
Line # 5 contain: Int:       , Exp:        in  0 values: <>
Line # 6 contain: Int:    300, Exp:   5000 in  4 values: <5 300 5000 2522>
Line # 7 contain: Int:       , Exp:        in  0 values: <>

或过滤同时包含Exp- Int-行:

i=0
while read string ;do
    if [ "$string" != "${string#*Int-*Exp-}" ];then
        ((i++))
        int=${string#*Int-}
        int=(${int//[a-z_-]/ })
        exp=${string#*Exp-}
        exp=(${exp//[a-z_-]/ })
        var=(${string//[a-z_-]/ })
        printf "Line #%2d contain: Int: %6s, Exp: %6s in %2d values: <%s>\n" \
            $i "$int" "$exp" ${#var[@]} "${var[*]}"
      fi
  done <<<'
newSetupSL5_snolab_Int-300_Exp-10000_3515

snolab_Int-300_Exp-10000_1185

newSetupSL5_snolab_Int-300_Exp-5000_2522
'
Line # 1 contain: Int:    300, Exp:  10000 in  4 values: <5 300 10000 3515>
Line # 2 contain: Int:    300, Exp:  10000 in  3 values: <300 10000 1185>
Line # 3 contain: Int:    300, Exp:   5000 in  4 values: <5 300 5000 2522>
于 2013-10-16T09:24:10.413 回答