Como posso extrair um número de um nome de arquivo que ocorre antes de uma determinada string?

0

Eu tenho muitos arquivos

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

Eu quero escrever um comando que extrai o número de cada arquivo que ocorre antes da palavra "livretos" (onde o caso é ignorado). Então, a saída da execução desse comando deve resultar em

$ 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

Como posso fazer isso?

    
por Brian Fitzpatrick 31.03.2018 / 00:09

4 respostas

2

O operador de teste condicional da Bash, [[ , pode comparar nomes de arquivos com uma expressão regular e extrair expressões com parênteses:

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

Isso fará um loop em todos os arquivos que corresponderem à palavra (não sensível a maiúsculas e minúsculas) "livretos" no diretório atual. Se você quer que algo seja executado em um único arquivo por vez, você pode simplificar o que está acima e colocá-lo em um script ou uma função:

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

... e depois ligue:

$ 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!
    
por 09.04.2018 / 13:17
3

Usando uma implementação grep que conhece o -o flag e tr :

#!/bin/sh

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

Este é um script sh (não bash , embora funcione com bash também). Ele presume que nenhuma string passada para ele na linha de comando possui uma nova linha literal embutida nele.

A expressão regular estendida [0-9]+[^0-9]*booklets corresponderá a qualquer sequência que se pareça com <integer><zero or more non-digit characters><"booklets"> e com -o , é exatamente isso que será retornado de grep . O tr simplesmente exclui qualquer coisa na saída de grep que não seja um dígito ou uma nova linha.

O tr pode ser substituído por sed 's/[^0-9].*//' , o que exclui tudo, desde o primeiro caractere não dígito na string.

Teste:

$ 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

Note que as strings com espaços nelas precisam ser citadas.

    
por 31.03.2018 / 10:42
1

Eu fiz o pythonscript.py mencionado abaixo e canalizei a saída para pesquisar as correspondências necessárias. Eu poderia ter usado apenas python, mas eu queria usar o grep para pipeline a saída

O arquivo de entrada chamado inputfile file:

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

Uso:

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

O pythonscript.py contém:

#!/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()

A saída:

100
99
35
    
por 31.03.2018 / 06:26
1

Você pode tentar este sed

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