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
(,或者只是跟着另一个数字,这将使它成为一个不同的数字(例如,它会错误地认为41
是4
(*(0)"$i"!(.[0-9]*|[0-9]*)
:允许前导 0!(*[0-9]|*[0-9].)*(0)"$i"!(.[0-9]*|[0-9]*)
:如果数字没有前缀<number>.
,则匹配该数字,这将使它成为浮点数(例如1.4
(,或者以另一个数字为前缀,这将使它成为不同的数字(例如,它会错误地认为24
是4
(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