我有很多文件
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,因此将输出流水线化
输入文件名为inputfile
file:
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