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

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

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


当前回答

这是一个substring.sh文件

使用

`substring.sh $TEXT 2 3` # characters 2-3

`substring.sh $TEXT 2` # characters 2 and after 

Substring.sh遵循这一行

#echo "starting substring"
chars=$1
start=$(($2))
end=$3

i=0
o=""
if [[ -z $end ]]; then
  end=`echo "$chars " | wc -c`
else
  end=$((end))
fi
#echo "length is " $e
a=`echo $chars | sed  's/\(.\)/\1 /g'`
#echo "a is " $a
for c in $a
do
  #echo "substring" $i $e $c
  if [[ i -lt $start ]]; then
    : # DO Nothing
  elif [[ i -gt $end ]]; then
    break;
  else
    o="$o$c"
  fi
  i=$(($i+1))
done
#echo substring returning $o
echo $o

其他回答

我的答案将对你想从字符串中得到什么有更多的控制。下面是如何从字符串中提取12345的代码

str="someletters_12345_moreleters.ext"
str=${str#*_}
str=${str%_more*}
echo $str

如果你想提取像abc这样的字符或像_或-这样的特殊字符,这样会更有效。例如:如果你的字符串是这样的,你想要someletters_之后和_moreleters之前的所有内容。ext:

str="someletters_123-45-24a&13b-1_moreleters.ext"

使用我的代码,您可以确切地说出您想要什么。 解释:

#*它将删除前面的字符串,包括匹配的键。这里我们提到的键是_ 它将删除以下字符串,包括匹配的键。这里我们提到的键是_more*

自己做一些实验,你会发现这很有趣。

没有任何子过程,您可以:

shopt -s extglob
front=${input%%_+([a-zA-Z]).*}
digits=${front##+([a-zA-Z])_}

一个非常小的变体也可以在ksh93中工作。

遵循要求

我有一个文件名,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=$(命令)语法。

以下是我的做法:

FN=someletters_12345_moreleters.ext
[[ ${FN} =~ _([[:digit:]]{5})_ ]] && NUM=${BASH_REMATCH[1]}

解释:

Bash-specific:

[[]]为条件表达式 =~表示条件为正则表达式 如果前一个命令成功,&&将链接这些命令

正则表达式(RE): _([[:digit:]]{5})_

_是字面量,用于为被匹配的字符串划分/锚定匹配边界 ()创建捕获组 [[:digit:]]是一个字符类,我认为它不言自明 {5}表示前面的字符中的恰好五个,类(如本例中所示)或组必须匹配

In english, you can think of it behaving like this: the FN string is iterated character by character until we see an _ at which point the capture group is opened and we attempt to match five digits. If that matching is successful to this point, the capture group saves the five digits traversed. If the next character is an _, the condition is successful, the capture group is made available in BASH_REMATCH, and the next NUM= statement can execute. If any part of the matching fails, saved details are disposed of and character by character processing continues after the _. e.g. if FN where _1 _12 _123 _1234 _12345_, there would be four false starts before it found a match.

这里是纯参数替换,一个空字符串。注意,我只将一些字母和更多字母定义为字符。如果它们是字母数字,这将无法正常工作。

filename=someletters_12345_moreletters.ext
substring=${filename//@(+([a-z])_|_+([a-z]).*)}
echo $substring
12345