Remove várias expressões regulares da variável com sed

1

Tenho certeza de que isso é bem simples, mas não consigo encontrar um bom exemplo. Eu estou tentando analisar / proc / 1 / exe para encontrar o sistema init de uma caixa. Exe é um link simbólico para o sistema init, mas tem citações quando você informa o arquivo, que eu quero remover. Infelizmente, eu vi o apóstrofo regular (U + 0027) em exe e aspas simples direita e esquerda (U + 2018 e U + 2019). Isso varia entre os sistemas. Eu não tenho certeza se isso é devido ao shell que estou executando e / ou sua versão, se é o utilitário stat, ou se é o próprio sistema, eu acabei de ver todos esses três caracteres (às vezes misturados).

Por fim, só quero remover todos esses caracteres com o mesmo comando sed. Até agora eu só consegui fazer isso canalizando sed para outro comando sed.

Este é o arquivo exe inteiro:

$stat /proc/1/exe

  File: '/proc/1/exe' -> '/sbin/init'
  Size: 0           Blocks: 0          IO Block: 1024   symbolic link
Device: b9h/185d    Inode: 76948360    Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-02-01 14:52:39.101744022 -0700
Modify: 2017-01-25 12:52:20.741244423 -0700
Change: 2017-01-25 12:52:20.741244423 -0700
 Birth: -

Observe que neste exemplo são apenas os apóstrofos normais, mas também vi os outros caracteres de aspas. Então eu começo recebendo apenas o conteúdo que eu preciso:

$stat /proc/1/exe | grep File: | awk -F '->' '{print $2}'
'/sbin/init'

Agora, quero remover as aspas e a única maneira de remover todos os tipos diferentes de aspas é usar vários comandos sed:

$stat /proc/1/exe | grep File: | awk -F '->' '{print $2}' | sed 's/\xe2\x80\x98//g' | sed 's/\xe2\x80\x99//g' | sed 's/\x27//g'
 /sbin/init

Depois disso, eu apenas canalizo para outra instrução awk:

$stat /proc/1/exe | grep File: | awk -F '->' '{print $2}' | sed s'/\xe2\x80\x98//g' | sed 's/\xe2\x80\x99//g' | sed 's/\x27//g' | awk -F '/' '{print $NF}'
init

Estou ciente de / proc / 1 / comm ou apenas usando um ls em / proc / 1 / exe. A questão é como eu combino os três comandos sed em um. Deveria ler:

Se houver uma cotação esquerda ou uma cotação ou apóstrofe à direita, remova-a. E isso deve fazer isso em todas as ocorrências.

Em uma nota lateral, se alguém souber de um comando melhor para obter o sistema init de uma caixa (além de / proc / 1 / comm, como eu vi que não seja confiável) ou pode apenas tornar esses comandos mais eficientes, eu d estar interessado em aprendê-lo.

    
por Joshua Schaeffer 02.02.2017 / 01:30

2 respostas

0

Como outros apontaram, existem várias maneiras melhores de determinar a natureza do PID 1. Usar várias invocações de grep , sed e awk em um único pipeline quase nunca é uma boa ideia. Se grep não puder, use sed . Se sed não puder fazer isso (facilmente), use awk . Por isso:

stat /proc/1/exe | sed -n '/File:/{s/.*-> *[\xe2\x80\x98]//;s/[\xe2\x80\x99].*//p;q}'
    
por 02.02.2017 / 09:02
0

Uma abordagem ligeiramente diferente pode ser adotada aqui, que ainda atende à pergunta original de "como você combina os três comandos sed em um" e também melhora o comando em si. Sem dúvida, há muitas outras abordagens para resolver a questão secundária de como recuperar o sistema init.

Em vez de tentar remover o que você não precisa, você pode capturar o que precisa com grupos de captura e pode combinar vários valores usando conjuntos de caracteres. O conjunto de caracteres é indicado por colchetes "[]". Dentro de você colocar exatamente o que você quer combinar em um você recebe uma instrução OR implícita entre eles. Assim, para corresponder à citação à esquerda OU , um apóstrofo que você usa:

[\xe2\x80\x98 \x27]

A aspa esquerda é o caractere hexadecimal "e28098" e o apóstrofo é o caractere hexadecimal "27". Eu coloquei um espaço entre eles apenas para enfatizar os dois caracteres separados, mas tecnicamente isso irá corresponder a uma citação esquerda OR um espaço OR um apóstrofo. Remova o espaço se você não quiser combinar nele. Você também pode adicionar "e28099" se quiser corresponder à cotação correta.

Para melhorar o comando em si e apenas extrair "init" ou "systemd", você pode adotar uma abordagem diferente usando grupos de captura. Grupos de captura são indicados por parênteses "()". Você pode então referenciar esse grupo de captura. Por exemplo, acabei usando esse comando para capturar exatamente o que precisava:

stat /proc/1/exe | sed -rn 's/^.*File:.*->.*[\xe2\x80\x98\x27]\/.*\/(.+)[\xe2\x80\x99\x27]$//p'

O grupo de captura (o ". +" entre parênteses) captura qualquer coisa depois da última barra que está entre uma citação à esquerda ou um apóstrofo e uma citação à direita ou apóstrofo. Ele é referenciado usando "\ 1" (como é o primeiro e único grupo de captura). Sed substitui toda a linha com o que está no grupo de captura.

  • -r é usado para expressões regulares estendidas (pelo menos na minha versão do sed)
  • -n é usado para suprimir a impressão. Quando combinada com a opção "/ p", imprimirá apenas linhas que correspondam ao padrão, mas depois de terem sido substituídas. Isso faz com que o sed funcione como o grep.

Espero que isso ajude alguém.

    
por 02.02.2017 / 22:53