Existe uma maneira de filtrar e imprimir um padrão específico sem repetir o código?

3

Se eu usar o pacman para instalar o software, ocasionalmente me deparo com erros do formulário

package-name: /some/package/file exists in filesystem

Isso geralmente ocorre se eu estraguei uma instalação em algum momento no passado, tentei instalar algo manualmente e assim por diante.

Para lidar com o problema, é útil ter os nomes de todos os pacotes conflitantes juntos em um arquivo. Eu posso fazer isso usando

# pacman -S package-name |
   grep '^package-name: [^ ]* exists in filesystem$' |
   sed 's/^package-name: \([^ ]*\) exists in filesystem$//' >
   conflicting_files.txt

No entanto, isso requer que eu digite a mesma coisa duas vezes. Existe uma maneira de fazer a mesma coisa sem duplicar o regex?

    
por John Gowers 27.09.2017 / 16:29

3 respostas

11

Muitas maneiras. Por exemplo, usando sed sozinho (estou assumindo ferramentas GNU aqui, já que você está usando pacman ):

pacman -S package-name |
   sed -En 's/^package-name: ([^ ]*) exists in filesystem$//p' >
   conflicting_files.txt

Ou grep :

pacman -S package-name |
   grep -oP '^package-name: \K\S+' >
   conflicting_files.txt

Se você precisa igualar o fim da linha, use a sugestão <@a> da

Ou perl :

pacman -S package-name |
   perl -ne 's/^package-name: (\S*) exists in filesystem$/$1/ && print' >
   conflicting_files.txt

Ou perl :

pacman -S package-name |
    perl -lane 'print $F[1] if /^package-name:.*exists in filesystem$/' >
    conflicting_files.txt

Ou awk :

pacman -S package-name |
    awk '/^package-name:.*exists in filesystem$/{print $2}' > 
    conflicting_files.txt
    
por 27.09.2017 / 18:22
3

Com o GNU grep você pode encurtar seu pipeline para o seguinte:

pacman -S package-name | grep -Po '^package-name: \K[^[:space:]]+(?= exists in filesystem$)' > conflicting_files.txt

Como alternativa, você também pode alterar [^[:space:]] para \S para corresponder à sequência não espaçada .

    
por 27.09.2017 / 16:39
3

Apenas jogando outra opção:

packman -S package-name |
  pcregrep -xo1 'package-name: (\S+) exists in filesystem'

Semelhante a:

packman -S package-name |
  perl -lne 'print $1 if /^package-name: (\S+) exists in filesystem$/'

O caminho portátil / POSIX seria:

sed -n 's/^package-name: \([^ ]*\) exists in filesystem$//p'
    
por 27.09.2017 / 18:27