Substitua uma linha em um arquivo por partes dessa linha

Substitua uma linha em um arquivo por partes dessa linha

Eu recebi uma lista de programas instalados na minha caixa do Ubuntu usandoapt list --installed

Aqui está um trecho da lista

wdiff/xenial,now 1.2.2-1build1 amd64 [installed,automatic]
wget/xenial-updates,xenial-security,now 1.17.1-1ubuntu1.5 amd64 [installed]
whiptail/xenial,now 0.52.18-1ubuntu2 amd64 [installed]
xauth/xenial,now 1:1.0.9-1ubuntu2 amd64 [installed]
xdg-user-dirs/xenial-updates,now 0.15-2ubuntu6.16.04.1 amd64 [installed]
xfsprogs/xenial-updates,now 4.3.0+nmu1ubuntu1.1 amd64 [installed]
xkb-data/xenial,now 2.16-1ubuntu1 all [installed]

Preciso do nome e da versão do programa. Por exemplo:
wdiff/xenial,now 1.2.2-1build1 amd64 [installed,automatic] torna-se
wdiff 1.2.2-1build1

Eu criei este comando que funciona.

apt list --installed  | sed -r 's@/@ @g' | awk '{print $1 "\t" $3}'  | sort -u

Gostaria de saber como usar apenas o sed para criar um novo arquivo com partes da linha do arquivo de entrada.

Esta regex: ^([^\/]+)\/[^\s]+\s([^\s]+)

  • Captura do início da linha até o primeiro /
  • Ignorar para o primeiro espaço em branco
  • Capture após o primeiro espaço em branco para o segundo espaço em branco

E eu deveria ser capaz de usar referências anteriores do sed para os grupos de captura e construir a nova saída.

apt list --installed | sed -r 's/^([^\/]+)\/[^\s]+\s([^\s]+)/\1 \2/'

No entanto, parece que a saída não corresponde à minha expectativa.

wdiff   [installed,automatic]
wget/xenial-updates,xenial-security,now 1.17.1-1ubuntu1.5 amd64 [installed]
whiptail    [installed]
xauth   [installed]
xdg-user-dirs/xenial-updates,now 0.15-2ubuntu6.16.04.1 amd64 [installed]
xfsprogs/xenial-updates,now 4.3.0+nmu1ubuntu1.1 amd64 [installed]
xkb-data    [installed]

O que está errado?

Responder1

O que está errado? Você capturou o grupo errado e não descartou até o final da string de entrada após a última correspondência que queria manter, apenas até o próximo não-espaço em branco

sed -r 's/^([^\/]+)\/[^\s]+\s([^\s]+)/\1    \2/'

([^/]+)   #capture everything up to /, OK
/         #discard the /. OK
[^\s]     #discard the next non white-space group, this is the bit you actually want
\s        #discard the whitespace
([^\s]+)  #capture the next non-whitespace group
#leave anything after the last non-whitespace found

Você provavelmente acabou fazendo isso por causa da baixa legibilidade de todas as fugas. Se você limpar, isso o ajudará a depurar

sed -E 's|([^/]*)[^ ]* +([^ ]*).*|\1 \2|' infile | column -t

([^/]*)    #capture up to the /
[^ ]* +    #discard until the space and any spaces
([^ ])     #capture the next character group until a space
.*         #discard to the end of the string

A menos que você tenha especificado uma correspondência global ( s///g), você não precisa da ^âncora.

Use |como separador para evitar escapes desnecessários na string correspondente

O column -tfaz um trabalho de alinhamento melhor do que vários espaços

Responder2

Tente o seguinte regex (não otimizado):

$ sed 's/\(^.*\)\(\/[^ ]* \)\([^ ]* \)\([^ ]* \)\([^ ]*\)/\1 \3/' infile
wdiff 1.2.2-1build1 
wget 1.17.1-1ubuntu1.5 
whiptail 0.52.18-1ubuntu2 
xauth 1:1.0.9-1ubuntu2 
xdg-user-dirs 0.15-2ubuntu6.16.04.1 
xfsprogs 4.3.0+nmu1ubuntu1.1 
xkb-data 2.16-1ubuntu1 

informação relacionada