Retirando um certo valor de uma string via regex

0

Eu vejo um monte de exemplos, mas eu simplesmente não consigo fazer isso funcionar. O grep pode produzir apenas agrupamentos especificados que correspondem? por exemplo, parece que deveria funcionar, mas recebo erros ou nenhuma saída.

Eu quero fazer:

pathname="/a/long/path/of/mine/2x02 - bar.mp4"

Todos os exemplos serão o caminho longo, um ou dois dígitos, xe, em seguida, 2 dígitos seguidos de um espaço, um - e um nome de arquivo.

Eu quero analisar isso para o valor 02: link mostra que \ d {1,2} x (\ d \ d) deve ter correspondência 1 = 02 neste exemplo.

O que não consigo descobrir é se tenho

echo "$pathname" | sed -n 's/.*\d{1,2}x\(\d\d\)//p'

ou

echo $pathname | grep -oP '\d{1,2}x(\d\d)'

Eu não recebo nada. Eu posso fazer:

echo $pathname | grep -oP '(\d\d)'

mas pode haver casos em que haja outros valores de 2 dígitos seguidos, como se eu tivesse

/a/long/path/of/mine/12x02 - bar.mp4

caso em que não acho que o acima irá especificar o segundo jogo, então eu prefiro o regex mais específico ... SE eu puder usar grupos de correspondência ou algo assim. Estou tentando fazer isso no bash no Scientific Linux 7.1.

    
por jmp242 09.09.2015 / 22:42

3 respostas

1

Como você estava usando grep com PCRE ( -P ), você pode usar esse padrão de Regex:

grep -Po '\d{1,2}x\K\d{2}(?= )' <<<"$pathname"
  • \d{1,2}x corresponderá a um ou dois dígitos seguido por x e, em seguida, \K descartará a correspondência

  • \d{2} corresponderá exatamente a dois dígitos, o padrão lookahead positivo de largura zero (?= ) garante que tenhamos um espaço após os dois dígitos.

Então, isso deve atender aos seus requisitos.

Exemplo:

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/2x02 - bar.mp4'
02

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/34x12 - bar.mp4'
12

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/0x1 - bar.mp4'
## No match

$ grep -Po '\d{1,2}x\K\d{2}(?= )' <<<'/a/long/path/of/mine/00x1 - bar.mp4'
## No match
    
por 10.09.2015 / 00:38
0

Usando sed

Com sed no modo básico, as chaves precisam ser escapadas:

$ echo "$pathname" | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*//p'
02

Para maior portabilidade, usei [[:digit:]] no lugar de \d . Eu também adicionei .* ao final para remover o texto final.

Usando grep -P

grep -P suporta um recurso de look-behind, mas o texto visual deve ser de tamanho fixo. Assim, podemos procurar por um único dígito precedendo o x que precede os dois dígitos que queremos exibir:

$ echo "$pathname" | grep -oP '(?<=\dx)(\d\d)'
02

Caminho alternativo

Ambos os itens acima também funcionam com o caminho alternativo:

$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | grep -oP '(?<=\dx)(\d\d)'
02
$ echo '/a/long/path/of/mine/12x02 - bar.mp4' | sed -n 's/.*[[:digit:]]\{1,2\}x\([[:digit:]][[:digit:]]\).*//p'
02
    
por 09.09.2015 / 22:55
0

Usando apenas um shell posix

p=$pathname
p=${p##*/}
p=${p#*x}
p=${p%% *}
echo "$p"

#or on one line
p=${pathname##*/};p=${p#*x};p=${p%% *};echo "$p"
    
por 09.09.2015 / 23:14