Como extrair texto de uma string usando sed?


95

Minha string de exemplo é a seguinte:

This is 02G05 a test string 20-Jul-2012

Agora, da string acima, quero extrair 02G05. Para isso tentei o seguinte regex com sed

$ echo "This is 02G05 a test string 20-Jul-2012" | sed -n '/\d+G\d+/p'

Mas o comando acima não imprime nada e a razão pela qual acredito é que ele não é capaz de corresponder nada ao padrão que forneci ao sed.

Portanto, minha pergunta é o que estou fazendo de errado aqui e como corrigi-lo.

Quando tento a string acima e o padrão com python, obtenho meu resultado

>>> re.findall(r'\d+G\d+',st)
['02G05']
>>>

6
Python definitivamente não é sed. Seus sabores regex são bastante diferentes.
— tripleee

Respostas:


91

O padrão \dpode não ser compatível com o seu sed. Experimente [0-9]ou em [[:digit:]]vez disso.

Para imprimir apenas a correspondência real (não toda a linha correspondente), use uma substituição.

sed -n 's/.*\([0-9][0-9]*G[0-9][0-9]*\).*/\1/p'

6
Obrigado, funcionou bem. Mas tenho uma dúvida porque .*é necessário com sua regex porque quando tento sed -n 's/\([0-9]\+G[0-9]\+\)/\1/p'apenas imprime a linha inteira.
— RanRag

7
É por isso, não é? Substitua tudo o que vier antes e depois da correspondência por nada e, em seguida, imprima a linha inteira.
— tripleee

1
@tripleee Isso só 2G05não imprime 02G05. A expressão que funciona é's/.*\([0-9][0-9]G[0-9][0-9]*\).*/\1/p'
— Kshitiz Sharma

1
Isso o codifica para exatamente dois dígitos. Algo como sed -n 's/\(.*[^0-9]\)\?\([0-9][0-9]*G[0-9][0-9]*\).*/\2/p'seria mais geral. (Suponho que seus sedapoios \?para zero ou uma ocorrência.)
— triplo

Veja também stackoverflow.com/a/48898886/874188 de como substituir vários outros comum Perl escapa como \w, \s, etc.
— tripleee

98

Que tal usar grep -E?

echo "This is 02G05 a test string 20-Jul-2012" | grep -Eo '[0-9]+G[0-9]+'

3
+1 Isto é mais simples e também tratará corretamente o caso de múltiplas correspondências na mesma linha. Um sedscript complexo poderia ser criado para esse caso, mas por que se preocupar?
— tripleee de

egrepusa regexp estendida sede grepusa regexp padrão, egrepou grep -eou sed -Eusa regexp estendida, e o código python em questão usa PCRE (expressão regular comum de perl) GNU grep pode usar PCRE com -Popção.
— Felipe Buccioni

@FelipeBuccioni na verdade deveria ser egrepou grep -Eoused -r
— SensorSmith

Para uma única (primeira) correspondência, acrescente `| head -1` (sem backticks), conforme esta resposta a outra pergunta.
— SensorSmith

1
greptem -m 1que parar após a primeira partida.
— tripleee de


5

Em vez disso, tente isto:

echo "This is 02G05 a test string 20-Jul-2012" | sed 's/.* \([0-9]\+G[0-9]\+\) .*/\1/'

Mas observe, se houver dois padrões em uma linha, ele imprimirá o segundo.


Ou, mais geralmente, o último se houver várias correspondências.
— tripleee

0

Tente usar o rextract . Ele permitirá que você extraia o texto usando uma expressão regular e o reformate.

Exemplo:

$ echo "This is 02G05 a test string 20-Jul-2012" | ./rextract '([\d]+G[\d]+)' '${1}'

2G05

Se isso usar regex padrão, os colchetes ao redor \dsão completamente supérfluos.
— tripleee
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.