Usando sed para recuperar parte de uma linha

7

Eu tenho o comando git svn assim:

git svn log --limit=1 --oneline

Ele será impresso on-line assim:

r12345 | <anything, as it is svn comment inputted by svn-user>

Estou tentando canalizar o comando sed para obter o 12345único, no entanto, não consigo fazê-lo funcionar. Existem muitos erros e o atual éparenthesis not balanced

meu último comando foi o seguinte:

git svn log --limit=1 --oneline | sed -e 's/r\(0-9) |*/\1/'

Eu pesquisei no Google e a documentação do sed não é muito clara ... Não sou muito boa com regex e minha melhor experiência é com o git --grepque é regex simplificado com boa documentação.

O ambiente é o terminal MacOSX, se for o caso.

EDITAR:

sed -n 's/r\(0-9*\)/\1/ funciona, mas retorna uma string vazia.

Zennichimaro
fonte

Respostas:

14

Aqui está uma solução sem regex, porque

Algumas pessoas, quando confrontadas com um problema, pensam "eu sei, vou usar expressões regulares". Agora eles tem dois problemas.

(leve com um grão de sal)

Você pode usar cutduas vezes:

git svn log --limit=1 --oneline | cut -d ' ' -f 1 | cut -c 2-

O primeiro cut ( cut -d ' ' -f 1) define o espaço como delimitador de coluna e seleciona apenas a primeira coluna r12345. O segundo corte ( cut -c 2-) seleciona o caractere na posição 2 e depois ( 2-).

gronostaj
fonte
2
+1 para a solução sem regex e a explicação.
ValarMorghulis
2
Pelo que vale a pena, a citação em regex se aplica mais a casos mais complicados. Embora você certamente não precise de regex para esse problema, incentivaria o OP a se familiarizar com ele, pois é totalmente inestimável para correspondência e extração de texto. Eu também consideraria mais simples que a sua solução, para ser honesto (é claro, em parte porque eu já sei regex).
Kat
7

Você está quase lá

sed -e 's/r\([0-9]*\) .*/\1/'

Você precisa dizer ao sed o que você quer \([0-9]*\)e o que não quer / r&.*/

Nifle
fonte
O [0-9]*é ganancioso, então eu não acho que o espaço no meio faça alguma coisa útil.
21417 Tom Tomech
1
Os solucionadores REGEX modernos procuram, em primeiro lugar, as seqüências fixas correspondentes (aqui re espaço), para que possa acelerar um pouco, dependendo de um solucionador, é claro.
loa_in_
Estamos realmente falando sobre acelerar uma regex em uma única linha de texto onde vários processos são iniciados? :)
Tom Fenech
3

Sinto que sednem sequer é a melhor ferramenta aqui, já que isso é para modificar a linha, mas vejo isso mais como um problema de extração. Para qual regex com grupos é um caminho bastante razoável. Por qualquer motivo, grepnão há como extrair grupos, o que acho estranho. Felizmente pcregrepfaz.

pcregrep -o1 "^r([0-9]+)"

Irá corresponder ao padrão "r" seguido por alguns números, apenas no início da linha (é o que ^acontece - caso contrário, você poderá extrair várias correspondências se a mensagem de confirmação se referir a outro commit). O -o1é extrair o 1º grupo. Exemplo:

$ echo "r12345 | <anything>" | pcregrep -o1 "^r([0-9]+)"
12345

Por que usar isso em vez de sed? Puramente por simplicidade. Você só precisa extrair algo, para poder usar regex puro. Eu vejo isso como muito mais simples que a sedresposta.

Kat
fonte
A extração é um uso perfeitamente válido e convencional de sed. Tome este formato comumente visto sed -n '/foo/p'(age exatamente como grep foo). Ou sed 10q(o mesmo que head -10) Confira sed.sourceforge.net/sed1line.txt para muitos outros exemplos.
Camada B
É justo o suficiente, @BLayer. Acho que mais do que eu queria era que, embora sed seja extremamente poderoso, eu o veja como bastante complicado. Muitas vezes, mais poderoso do que se poderia desejar para o trabalho.
Kat
-1
Uma outra alternativa pode ser:

$ eco "r12345 |" | sed -n 's / ^ r \ ([0-9] * \). * $ / \ 1 / p'
12345
$ _
Joe
fonte
2
Mesmo que isso possa resolver o problema, sempre acompanhe todas as respostas de código com uma explicação.
pulsejet
Isso é quase exatamente o mesmo que a primeira resposta . Como é diferente? É melhor de alguma forma?
Scott
Sim, regexp é semelhante. Mas a diferença está na opção `-n 'passada da linha de comando para` sed', e com o comando `p 'para imprimir exatamente o que fazer. Útil no caso de `canalizar 'várias linhas também.
joe