如何从文件名中提取给定字符串之前出现的数字?

如何从文件名中提取给定字符串之前出现的数字?

我有很多文件

101s18-exam02--100-booklets.pdf
MATH232 Exam 01 99 booklets.pdf
35BOOKLETS.pdf

我想编写一个命令,从每个文件中提取单词“booklets”之前出现的数字(忽略大小写)。因此,运行此命令的输出应该是

$ bash mycommand.sh 101s18-exam02--100-booklets.pdf
100

$ bash mycommand.sh MATH232 Exam 01 99 booklets.pdf
99

$ bash mycommand.sh 35BOOKLETS.pdf
35

我怎样才能做到这一点?

答案1

使用grep知道该-o标志的实现,并且tr

#!/bin/sh

printf '%s\n' "$@" | grep -oiE '[0-9]+[^0-9]*booklets' | tr -dc '0-9\n'

这是一个sh脚本(不是bash,尽管它也可以使用bash)。它假设命令行上传递给它的字符串中没有嵌入文字换行符。

扩展的正则表达式[0-9]+[^0-9]*booklets将匹配任何看起来像<integer><zero or more non-digit characters><"booklets">and的字符串-o,这正是从 中返回的内容grep。只是tr删除输出中除grep数字或换行符之外的所有内容。

可以tr替换为sed 's/[^0-9].*//',这会删除字符串中第一个非数字字符中的所有内容。

测试它:

$ sh script.sh 101s18-exam02--100-booklets.pdf
100
$ sh script.sh "MATH232 Exam 01 99 booklets.pdf"
99
$ sh script.sh 35BOOKLETS.pdf
35

$ sh script.sh 101s18-exam02--100-booklets.pdf "MATH232 Exam 01 99 booklets.pdf" 35BOOKLETS.pdf
100
99
35

请注意,其中包含空格的字符串需要用引号引起来。

答案2

Bash 的条件测试运算符[[可以将文件名与正则表达式进行比较并提取括号表达式:

shopt -s nocaseglob
for f in *booklets*
do
  [[ $f =~ ([[:digit:]]+)[^[:digit:]]?booklets ]] && echo "${BASH_REMATCH[1]}"
done

这将循环遍历当前目录中包含(不区分大小写)单词“booklets”的每个匹配文件。如果您希望一次针对单个文件执行某些操作,您可以简化上述内容并将其放入脚本或函数中:

extractnumber ()
(
    shopt -s nocaseglob
    if [ ! -f "$1" ]; then echo "File $1 not found!"; return 1; fi
    [[ $1 =~ ([[:digit:]]+)[^[:digit:]]?booklets ]] && echo "${BASH_REMATCH[1]}";
)

...然后调用它:

$ extractnumber 35BOOKLETS.pdf
35
$ extractnumber MATH232\ Exam\ 01\ 99\ booklets.pdf
99
$ extractnumber 101s18-exam02--100-booklets.pdf
100
$ extractnumber foobar
File foobar not found!

答案3

我已按照下面所述完成操作pythonscript.py ,并将输出流水线化以搜索所需的匹配项。我本来可以只使用 python,但我希望使用 grep,因此将输出流水线化

输入文件名为inputfilefile:

101s18-exam02--100-booklets.pdf
MATH232 Exam 01 99 booklets.pdf
35BOOKLETS.pdf

用法:

python pythonscript.py |grep -o "^[0-9]*"

其中pythonscript.py包含:

#!/usr/bin/python
import re
o = open('inputfile','r')
k=re.compile(r'\d{2,3}\s?-?booklets',re.IGNORECASE)
for g in o:
    u=re.search(k,g)
    if u:
       print u.group()

输出:

100
99
35

答案4

你可以试试这个sed

sed -E '
  s/^/ /
  s/.*[^0-9]([0-9]+).?[bB][oO]{2}[kK][lL][eE][tT][sS].*/\1/
' infile

相关内容