Como usar um comando shell para mostrar apenas a primeira e a última coluna em um arquivo de texto?

Como usar um comando shell para mostrar apenas a primeira e a última coluna em um arquivo de texto?

Preciso de ajuda para descobrir como usar o comando sed para mostrar apenas a primeira e a última coluna em um arquivo de texto. Aqui está o que tenho até agora para a coluna 1:

cat logfile | sed 's/\|/ /'|awk '{print $1}'

Minha fraca tentativa de exibir também a última coluna foi:

cat logfile | sed 's/\|/ /'|awk '{print $1}{print $8}'

No entanto, isso pega a primeira coluna e a última coluna e as mescla em uma lista. Existe uma maneira de imprimir a primeira coluna e as últimas colunas claramente com os comandos sed e awk?

Exemplo de entrada:

foo|dog|cat|mouse|lion|ox|tiger|bar

Responder1

Quase lá. Basta colocar as duas referências de coluna próximas uma da outra.

cat logfile | sed 's/|/ /' | awk '{print $1, $8}'

Observe também que você não precisa cataqui.

sed 's/|/ /' logfile | awk '{print $1, $8}'

Observe também que você pode dizer awkque os separadores de coluna são |, em vez de espaços em branco, portanto você não precisa sedde nenhum deles.

awk -F '|' '{print $1, $8}' logfile

ConformesugestõesporCalebe, se você quiser uma solução que ainda produza o último campo, mesmo que não haja exatamente oito, você pode usar $NF.

awk -F '|' '{print $1, $NF}' logfile

Além disso, se desejar que a saída retenha os |separadores, em vez de usar um espaço, você poderá especificar os separadores de campo de saída. Infelizmente, é um pouco mais desajeitado do que apenas usar a -Fbandeira, mas aqui estão três abordagens.

  • Você pode atribuir os separadores de campos de entrada e saída por awksi só, no bloco BEGIN.

    awk 'BEGIN {FS = OFS = "|"} {print $1, $8}' logfile
    
  • Você pode atribuir essas variáveis ​​ao chamar awka partir da linha de comando, por meio do -vsinalizador.

    awk -v 'FS=|' -v 'OFS=|' '{print $1, $8}' logfile
    
  • ou simplesmente:

    awk -F '|' '{print $1 "|" $8}' logfile
    

Responder2

Você está usando awkde qualquer maneira:

awk '{ print $1, $NF }' file

Responder3

Basta substituir do primeiro ao último |por um |(ou espaço se preferir):

sed 's/|.*|/|/'

Observe que embora não haja sedimplementação onde |é especial (desde queestendidoexpressões regulares não são habilitadas em -Eou -rem algumas implementações), \|em si é especial em algumas como GNU sed. Então você deverianãoescape |se você pretende que corresponda ao |personagem.

Se substituir por espaço e se a entrada já puder conter linhas com apenas one |, você terá que tratar isso especialmente, pois |.*|não corresponderá a elas. Isso poderia ser:

sed 's/|\(.*|\)\{0,1\}/ /'

(isto é, tornar a .*|parte opcional) Ou:

sed 's/|.*|/ /;s/|/ /'

ou:

sed 's/\([^|]*\).*|/\1 /'

Se você quiser o primeiro e o oitavo campos, independentemente do número de campos na entrada, basta:

cut -d'|' -f1,8


(todos eles funcionariam com qualquer utilitário compatível com POSIX assumindo que a entrada forma texto válido (em particular, aqueles sedgeralmente não funcionarão se a entrada tiver bytes ou sequências de bytes que não formam caracteres válidos no local atual, como por exemplo printf 'unix|St\351phane|Chazelas\n' | sed 's/|.*|/|/'em uma localidade UTF-8)).

Responder4

Parece que você está tentando obter o primeiro e o último campos de texto delimitados por |.

Presumi que seu arquivo de log contém o texto abaixo,

foo|dog|cat|mouse|lion|ox|tiger|bar
bar|dog|cat|mouse|lion|ox|tiger|foo

E você quer uma saída como,

foo bar
bar foo

Se sim, então aqui vem o comando para o seu

Através do GNU sed,

sed -r 's~^([^|]*).*\|(.*)$~\1 \2~' file

Exemplo:

$ echo 'foo|dog|cat|mouse|lion|ox|tiger|bar' | sed -r 's~^([^|]*).*\|(.*)$~\1 \2~'
foo bar

informação relacionada