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.