Não precisa da linha inteira, apenas a correspondência da expressão regular

7

Eu simplesmente preciso obter a correspondência de uma expressão regular:

$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"

A saída deve ser apenas o que foi correspondido, dentro dos parênteses.

Não pense que eu posso usar grep porque corresponde à linha inteira.

Por favor, deixe-me saber como fazer isso.

    
por Alex L 06.08.2009 / 18:34

7 respostas

6

2 coisas:

  • Como afirmado pela @Rory, você precisa da opção -o , portanto, apenas a correspondência é impressa (em vez da linha inteira)
  • Além disso, você encontra a opção -P , para usar expressões regulares Perl, que incluem elementos úteis como Antecipe (?= ) e Olhe para trás (?<= ) , eles procuram por peças, mas não combinam e imprimem.

Se você deseja que apenas a parte dentro do parensis seja correspondida:

grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt

se o arquivo contiver o sting /(a)5667/ , o grep imprimirá 'a', porque:

  • /( são encontrados por \/\( , mas porque eles estão em um look-behind (?<= ) eles não são reportados
  • a é correspondido por \w e, portanto, é impresso (por causa de -o )
  • )5667/ são encontrados b < \).+\/ , mas porque estão em look-ahead (?= ) eles não são reportados
por 20.01.2015 / 14:21
14

Use a opção -o em grep .

Por exemplo:

$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar
    
por 06.08.2009 / 18:36
4

Se você quer apenas o que está entre parênteses, você precisa de algo que suporte a captura de sub-correspondências (grupos de captura nomeados ou numerados). Eu não acho que grep ou egrep possam fazer isso, perl e sed podem. Por exemplo, com perl:

Se um arquivo chamado foo tiver uma linha, será o seguinte:

/adsdds      /

E você faz:

perl -nle 'print $1 if /\/(\w).+\//' foo

A letra a é retornada. Isso pode não ser o que você quer. Se você nos disser o que está tentando corresponder, poderá obter ajuda melhor. $ 1 é o que quer que tenha sido capturado no primeiro conjunto de parênteses. $ 2 seria o segundo set, etc.

    
por 06.08.2009 / 19:38
3

Como você marcou sua pergunta como bash além de shell , há outra solução além do grep :

O Bash tem seu próprio mecanismo de expressão regular desde a versão 3.0, usando o operador =~ , assim como o Perl.

agora, dado o seguinte código:

#!/bin/bash
DATA="test <Lane>8</Lane>"

if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
        echo $BASH_REMATCH
        echo ${BASH_REMATCH[1]}
fi
  • Observe que você precisa invocá-lo como bash e não apenas sh para obter todas as extensões
  • $BASH_REMATCH dará a string inteira como correspondida por toda a expressão regular, portanto <Lane>8</Lane>
  • ${BASH_REMATCH[1]} dará a parte correspondente ao 1º grupo, portanto, apenas 8
por 20.01.2015 / 14:47
2
    sed -n "s/^.*\(captureThis\).*$//p"

-n      don't print lines
s       substitute
^.*     matches anything before the captureThis 
\( \)   capture everything between and assign it to  
.*$     matches anything after the captureThis 
      replace everything with captureThis 
p       print it
    
por 22.04.2016 / 17:58
0

Isso vai conseguir o que você está pedindo, mas não acho que seja o que você realmente quer. Eu coloquei o .* na frente do regex para comer qualquer coisa antes do jogo, mas essa é uma operação gananciosa, então isso só combina com o penúltimo caractere \w na string.

Note que você precisa escapar dos parens e do + .

sed 's/.*\(\w\).\+//' myfile.txt
    
por 06.08.2009 / 20:02
0

Supondo que o arquivo contenha:

$ cat file
Text-here>xyz</more text

E você quer o (s) caractere (s) entre > e </ , você pode usar:

grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed -nE 's:^.*>(\w+)</.*$::p' file
awk '{print(gensub("^.*>(\w+)</.*$","\1","g"))}' file
perl -nle 'print $1 if />(\w+)<\//' file

Tudo irá imprimir uma string "xyz".

Se você deseja capturar os dígitos desta linha:

$ cat file
Text-<here>1234</text>-ends

grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed -E 's:^.*>([0-9]+)</.*$::' file
awk '{print(gensub(".*>([0-9]+)</.*","\1","g"))}' file
perl -nle 'print $1 if />([0-9]+)<\//' file

    
por 22.07.2017 / 10:01