给定someletters_12345_moreleters形式的文件名。ext,我想提取5位数字,并将它们放入一个变量。

为了强调这一点,我有一个x个字符的文件名,然后是一个5位数字序列,两边都有一个下划线,然后是另一组x个字符。我想把这个5位数代入一个变量。

我对实现这一目标的多种不同方式非常感兴趣。


当前回答

您可以使用参数展开来做到这一点。

如果a为常数,则下面的参数展开执行子字符串提取:

b=${a:12:5}

12是偏移量(从零开始),5是长度

如果数字周围的下划线是输入中唯一的下划线,您可以分两步分别去掉前缀和后缀:

tmp=${a#*_}   # remove prefix ending in "_"
b=${tmp%_*}   # remove suffix starting with "_"

如果有其他下划线,那么无论如何都可能是可行的,尽管比较棘手。如果有人知道如何在一个表达式中执行两个展开,我也想知道。

提出的两个解决方案都是纯bash,不涉及进程生成,因此非常快。

其他回答

很多过时的解决方案都需要管道和子外壳。 自bash版本3(2004年发布)以来,它有一个内置的正则表达式比较操作符=~。

input="someletters_12345_moreleters.ext"
# match: underscore followed by 1 or more digits followed by underscore
[[ $input =~ _([0-9]+)_ ]]
echo ${BASH_REMATCH[1]}

输出:

12345

注意,如果您不是很精通编写RegExp,我建议您阅读精通正则表达式。

如果您只是需要弄清楚如何让RegExp工作,并且它不符合您的想法,请尝试RegEx101.com的在线GUI,并将“Flavor”设置为“PCRE”,以便获得bash使用的[[:digit:]]等POSIX风格的字符类。

遵循要求

我有一个文件名,x个字符,然后是5位数字 序列两侧分别用一个下划线包围 x个字符的集合。我想取一个5位数 把它代入一个变量。

我发现了一些可能有用的grep方法:

$ echo "someletters_12345_moreleters.ext" | grep -Eo "[[:digit:]]+" 
12345

或更好的

$ echo "someletters_12345_moreleters.ext" | grep -Eo "[[:digit:]]{5}" 
12345

然后使用-Po语法:

$ echo "someletters_12345_moreleters.ext" | grep -Po '(?<=_)\d+' 
12345

或者如果你想让它正好适合5个字符:

$ echo "someletters_12345_moreleters.ext" | grep -Po '(?<=_)\d{5}' 
12345

最后,要将它存储在一个变量中,只需要使用var=$(命令)语法。

外壳切割-从字符串中打印特定范围的字符或给定部分

#method1)使用bash

 str=2020-08-08T07:40:00.000Z
 echo ${str:11:8}

#方法2)使用cut

 str=2020-08-08T07:40:00.000Z
 cut -c12-19 <<< $str

#method3)当使用awk时

 str=2020-08-08T07:40:00.000Z
 awk '{time=gensub(/.{11}(.{8}).*/,"\\1","g",$1); print time}' <<< $str

试着用cut -c startindex - stopindx

bash解决方案:

IFS="_" read -r x digs x <<<'someletters_12345_moreleters.ext'

这将破坏一个名为x的变量。var x可以被更改为var _。

input='someletters_12345_moreleters.ext'
IFS="_" read -r _ digs _ <<<"$input"