如何查找字符串中是否缺少一系列非浮点数



In Bash

我想在字符串中找到一系列非浮点数。

如果我有这样的字符串:

"1.4.jpg 2.005.jpg 003: Blah.jpg Blah4.jpg 4.5.jpg"

我想找出数字firstNum-lastNum是否丢失。比如说,如果

firstNum=1
lastNum=5

该函数将返回

"1 个缺失,2 个缺失,5 个缺失"

在字符串中找到非浮点数相对容易,但让我的脚本感到困惑的是字符串的"2.005.jpg"部分。我的脚本不明白如何识别 5 是浮点数 2 的一部分,因此应该忽略它。

我只想说,如果数字前面有前导零或前面有"[0-9].",请忽略它。但不幸的是,我需要支持具有任意数量的前导零的数字。

如果您不反对使用awk,则可以使用此脚本:

echo "1.4.jpg 2.005.jpg 003: Blah.jpg Blah4.jpg" | 
awk -v min=1 -v max=5 -v RS="[^0-9. ]+" '
($0+0)!~/./&&/[0-9]+/{a[$0+0]}
END{for(i=min;i<=max;i++)if(!(i in a))print i " is missing"}'

这是一个 GNU awk 脚本,它依赖于记录分隔符RS来拆分仅包含(浮点数(数字的行。

诀窍是在找到的数字上加 0 并检查它是否仍然是十进制形式(没有任何点.(。如果是这样,则数字存储在数组a中。

END语句循环遍历从min(1( 到max(5( 的所有十进制数,如果该数字不是数组a的一部分,则打印一条消息。

符合 posix 标准的备用脚本如下:

echo "1.4.jpg 2.005.jpg 003: Blah.jpg Blah4.jpg" | 
awk -v min=1 -v max=5 '
{
split($0,n,"[^0-9. ]+"); 
for(i in n){
if((n[i]+0)!~/./&&n[i]~/[0-9]+/){
a[n[i]+0]
}
}
}
END{for(i=min;i<=max;i++)if(!(i in a))print i " is missing"}'

主要区别在于使用代替RS的函数split()split断开输入字符串并将数字放入数组n中。然后检查数组元素并将其放入数组a(如果是十进制数(。

看看这个 extglob 模式:

find_missing() {
shopt -s extglob
for(( i = $2; i <= $3; i++ )); do
[[ $1 = !(*[0-9]|*[0-9].)*(0)"$i"!(.[0-9]*|[0-9]*) ]] || printf '<%s> missing!n' "$i"
done
}

$i视为 4:

  • "$i":匹配数字
  • "$i"!(.[0-9]*|[0-9]*):匹配数字,如果它后面没有任何一个.<number>,这将使它成为一个浮点数(例如4.1(,或者只是跟着另一个数字,这将使它成为一个不同的数字(例如,它会错误地认为414(
  • *(0)"$i"!(.[0-9]*|[0-9]*):允许前导 0
  • !(*[0-9]|*[0-9].)*(0)"$i"!(.[0-9]*|[0-9]*):如果数字没有前缀<number>.,则匹配该数字,这将使它成为浮点数(例如1.4(,或者以另一个数字为前缀,这将使它成为不同的数字(例如,它会错误地认为244(
  • shopt -s extglob:启用扩展通配

试运转:

$ find_missing "1.4.jpg 2.005.jpg 003: Blah.jpg Blah4.jpg" 1 5
<1> missing!
<2> missing!
<5> missing!  
$ find_missing "1.4.jpg 2.005.jpg 003: Blah.jpg Blah4.jpg" 1 2
<1> missing!
<2> missing!
$ find_missing "001 3.002 A.4A" 1 4
<2> missing!
<3> missing!

可能的答案:

下面是一个bash函数,它以(希望(合理的方式在提供的测试用例上给出预期的输出值:

function check_missing {
prefix=""
for i in {1..5}; do
# make sure that $i is present, 
# with optional leading zeroes,
# but with at least one non-number
# *before* the zeroes and *after* $i
if ! [[ "$1" =~ .*[^0-9.]0*"$i".?[^0-9.].* ]]; then 
echo -n "${prefix}${i} is missing"
prefix=", "
fi
done
echo
}

我不确定这会如何推广到您拥有的其他输入(或输出格式有多重要(,但希望它至少给出了如何解决问题的想法。

示例输出:

> check_missing "001.004.jpg 2.005.jpg 003.jpg Blah4.jpg"
1 is missing, 2 is missing, 5 is missing
> check_missing "1.4.jpg 2.005.jpg 003: Blah.jpg Blah4.jpg"
1 is missing, 2 is missing, 5 is missing

最新更新