Como remover o texto depois de '-'?

6

Eu tenho uma lista de arquivos (basicamente eles são .deb packages). Vamos dizer:

abc-de-1.2.3-1.deb
fgh-ij-4.5.6-2.deb
klm-no-7.8.9-3.deb
pqrs-10.11.12-4.deb
...

Como você pode ver, alguns dos nomes de arquivos têm números depois de um - , enquanto outros têm algum texto depois de um - e, em seguida, números após o próximo - .

Existe alguma maneira de remover tudo a partir dos números, incluindo - , ou seja,

abc-de
fgh-ij
klm-no
pqrs
...

Eu quero editar a lista, não renomear os arquivos.

    
por Raphael 23.07.2017 / 08:21

5 respostas

8

Se você conseguir usar o primeiro número para identificar o que deseja remover todas as vezes, use:

$ sed 's/-[0-9].*//' file
abc-de
fgh-ij
klm-no
pqrs

Notas

  • s/old/new/ replace old com new
  • [0-9] algum dígito
  • .* qualquer número de caracteres
por Zanna 23.07.2017 / 08:23
6

Usando grep com expressões regulares Perl:

$ grep -Po "^[a-z-]*(?=-[0-9])" filename
abc-de
fgh-ij
klm-no
pqrs
    
por Ravexina 23.07.2017 / 09:41
4

Perl

$ perl -lne 's/([[:digit:]].*)//;s/-$//;print' input.txt                                                            
abc-de
fgh-ij
klm-no
pqrs

Isso realiza duas substituições, uma para excluir tudo o que começa com um dígito e remove o% arrastado-. Use -i opções adicionalmente para editar o arquivo original, como $ perl -i -lne 's/([[:digit:]].*)//;s/-$//;print' input.txt

Como alternativa, com correspondência e agrupamento de dígitos não desejados:

$ perl -lne 's/^(\D*)-.*//;print' input.txt                                                                                                        
abc-de
fgh-ij
klm-no
pqrs

AWK

$ awk -F '-' '{s=$1;for(i=2;i<=NF;i++) if($i~/[0-9].*/){print s;next}else{s=s"-"$i}}' input.txt 
abc-de
fgh-ij
klm-no
pqrs

A maneira como isso funciona é que tratamos - como separador para campos e, em seguida, iteramos sobre cada linha. Nós "armazenamos em cache" o primeiro campo e passamos a iterar usando for loop. Em cada iteração, verificamos se a coluna não contém um número em que a variável s é preenchida. Se a coluna contiver um número, imprimiremos o que foi salvo e passaremos para a próxima linha.

Use > new_file.txt no final para redirecionar a saída para o novo arquivo.

Python

#!/usr/bin/env python
import sys,re

with open(sys.argv[1]) as f:
    for line in f:
        tokens = re.split("-|\.",line.strip().replace(".deb",""))
        words_only = filter(lambda x: not x.isdigit(),tokens)
        print("-".join(words_only))

Usando re.split() , detalhamos cada linha na lista de tokens e filtramos apenas tokens não dígitos.

Alternativamente, aqui está um comando de uma linha. Isso não requer precaução no caso de não haver nenhum dígito na linha, portanto, use-o somente se tiver certeza de que todas as linhas contêm números.

$ python -c 'import re,sys;f=open(sys.argv[1]);print("\n".join([ l[:re.search(r"\d",l).start()-1] for l in f]))' input.txt

Números potenciais nos nomes dos pacotes

O hvd observou corretamente nos comentários que pode haver números inteiros em nomes de pacotes, às vezes, o que pode apresentar uma dificuldade na análise do arquivo de entrada, enquanto os nomes de versão geralmente possuem pontos neles. Com isso em mente, os comandos podem ser alterados um pouco para compensar isso:

$ perl -lne 's/\d*\..*//;s/-$//;print' input.txt

$ awk '{gsub(/[0-9]*\..*/,"");print substr($0,0,length($0)-1)};' input.txt                                                                           

$ python -c 'import re,sys;f=open(sys.argv[1]);print("\n".join([ l[:re.search(r"\d*\.",l).start()-1] for l in f]))' input.txt
    
por Sergiy Kolodyazhnyy 23.07.2017 / 08:39
4

Através do awk,

awk -F'-[0-9]' '{print $1}' file

No awk, podemos também passar um regex como um argumento para o Field Separator -F . Então, isso dividiria cada linha na parte em que a regex corresponde.

Exemplo:

$ echo 'abc-de-1.2.3-1.deb' | awk -F'-[0-9]' '{print $1}'
abc-de
    
por Avinash Raj 24.07.2017 / 07:51
1

Eu vou adivinhar, já que você sugeriu que os arquivos são pacotes DEB, então, talvez você quisesse algo como:

dpkg-query -f '${Package}\n' -W 'gnome*'

Onde, em vez de gnome* , você pode substituir qualquer padrão. Não sei exatamente qual é a convenção para nomear arquivos DEB, mas se esses são arquivos DEB, provavelmente é melhor confiar em dpkg para fornecer o nome do pacote.

E se esses arquivos forem DEB (no seu sistema), você poderá usar:

dpkg-deb --showformat='${Package}\n' -W some-file.deb 
    
por wvxvw 23.07.2017 / 16:18