给定someletters_12345_moreleters形式的文件名。ext,我想提取5位数字,并将它们放入一个变量。
为了强调这一点,我有一个x个字符的文件名,然后是一个5位数字序列,两边都有一个下划线,然后是另一组x个字符。我想把这个5位数代入一个变量。
我对实现这一目标的多种不同方式非常感兴趣。
给定someletters_12345_moreleters形式的文件名。ext,我想提取5位数字,并将它们放入一个变量。
为了强调这一点,我有一个x个字符的文件名,然后是一个5位数字序列,两边都有一个下划线,然后是另一组x个字符。我想把这个5位数代入一个变量。
我对实现这一目标的多种不同方式非常感兴趣。
当前回答
下面是一个前缀后缀解决方案(类似于JB和Darron给出的解决方案),它匹配第一个数字块,并且不依赖于周围的下划线:
str='someletters_12345_morele34ters.ext'
s1="${str#"${str%%[[:digit:]]*}"}" # strip off non-digit prefix from str
s2="${s1%%[^[:digit:]]*}" # strip off non-digit suffix from s1
echo "$s2" # 12345
其他回答
没有任何子过程,您可以:
shopt -s extglob
front=${input%%_+([a-zA-Z]).*}
digits=${front##+([a-zA-Z])_}
一个非常小的变体也可以在ksh93中工作。
您可以使用参数展开来做到这一点。
如果a为常数,则下面的参数展开执行子字符串提取:
b=${a:12:5}
12是偏移量(从零开始),5是长度
如果数字周围的下划线是输入中唯一的下划线,您可以分两步分别去掉前缀和后缀:
tmp=${a#*_} # remove prefix ending in "_"
b=${tmp%_*} # remove suffix starting with "_"
如果有其他下划线,那么无论如何都可能是可行的,尽管比较棘手。如果有人知道如何在一个表达式中执行两个展开,我也想知道。
提出的两个解决方案都是纯bash,不涉及进程生成,因此非常快。
我很惊讶这个纯粹的bash解决方案没有出现:
a="someletters_12345_moreleters.ext"
IFS="_"
set $a
echo $2
# prints 12345
您可能希望将IFS重置为之前的值,或者在之后取消设置IFS !
类似于php中的substr('abcdefg', 2-1, 3):
echo 'abcdefg'|tail -c +2|head -c 3
基于jor的回答(这对我来说并不适用):
substring=$(expr "$filename" : '.*_\([^_]*\)_.*')