AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 425044
Accepted
MLu
MLu
Asked: 2018-02-19 16:14:11 +0800 CST2018-02-19 16:14:11 +0800 CST 2018-02-19 16:14:11 +0800 CST

Como excluir o campo de entrada no AWK?

  • 772

Estou transformando alguns dados com awk(ou gawk) e quero deletar um dos campos de entrada antes de imprimir a saída novamente.

O que eu quero alcançar é isso:

~ $ echo 'field1,field2,field3' | awk -F, '{transform($1); delete($2); print $0;}'
new_field1,field3

Não posso simplesmente atribuir uma string vazia a $2porque isso leva a new_field1,,field3(observe as duas vírgulas).

Eu poderia imprimir explicitamente apenas os campos que desejo, mas isso não é muito elegante porque tenho muito mais campos do que 3 e também há campos opcionais no final (não mostrados aqui). Por isso prefiro print $0. Só precisa se livrar de alguns campos primeiro.

Qualquer ideia?

awk
  • 3 3 respostas
  • 1490 Views

3 respostas

  • Voted
  1. Best Answer
    cas
    2018-02-19T17:43:34+08:002018-02-19T17:43:34+08:00

    Excluir campos no awk é notoriamente difícil. Parece ser uma operação tão simples (e muitas vezes necessária), mas é mais difícil do que deveria ser.

    Consulte Existe uma maneira de excluir completamente os campos no awk, para que os delimitadores extras não sejam impressos? do Stack Overflow para uma boa maneira de fazer isso.

    Copiei a rmcol()função na resposta de @ghoti, para que tenhamos uma cópia aqui no U&L:

    function rmcol(col,     i) {
      for (i=col; i<NF; i++) {
        $i=$(i+1)
      }
      NF--
    }
    

    Ele exclui a coluna especificada da linha de entrada atual e diminui o contador de campo ( NF) para corresponder.

    Não tenho ideia do que sua transform()função faz, então nem tentarei duplicar isso - mas aqui está um exemplo de uso rmcol()em uma awklinha:

    $ echo 'field1,field2,field3' | awk -F, -v OFS=, '
      function rmcol(col,     i) {
        for (i=col; i<NF; i++) {
          $i=$(i+1)
        }
        NF--
      }
    
      { rmcol(2); print; }
      '
    field1,field3
    

    BTW, se você precisar excluir vários campos de uma linha de entrada, é melhor/mais fácil excluí-los na ordem inversa. Ou seja, exclua primeiro os campos com os números mais altos . Por quê? Como os campos de numeração mais alta serão renumerados toda vez que você excluir um campo de numeração mais baixa, tornando muito difícil acompanhar qual número de campo pertence a qual campo.


    BTW, delete()in awké para excluir elementos de uma matriz - não para excluir campos de uma linha de entrada. Você poderia split()inserir cada linha de entrada (on FS) em uma matriz e excluir o segundo elemento da matriz, mas teria que escrever uma join()função para imprimir a matriz com uma vírgula (ou OFS) separando cada campo.

    Mesmo fazer isso seria mais complicado do que seria de esperar, porque todos os arrays awksão arrays associativos (ou seja, eles não são indexados numericamente) - portanto delete(array[2]) , não mudará automaticamente os elementos do array 3+ para os elementos 2+. Você teria que escrever sua própria função wrapper delete()para fazer praticamente a mesma coisa para arrays que rmcol()faz para campos de entrada.

    • 7
  2. Sundeep
    2018-02-19T21:25:35+08:002018-02-19T21:25:35+08:00

    Algumas alternativas

    1) pré-processar a entrada para remover o campo primeiro, fácil de fazer cutse o separador de campo for de um único caractere

    $ s='field1,field2,field3'
    $ # use 'cut -d, -f1,3-' if --complement option is not available
    $ echo "$s" | cut -d, --complement -f2
    field1,field3
    $ echo "$s" | cut -d, --complement -f2 | awk 'BEGIN{FS=OFS=","} {$1="new"} 1'
    new,field3
    

    2) usarperl

    $ # indexing starts from 0, the array @F contains the input fields
    $ # $#F will give index of last element in the array
    $ echo "$s" | perl -F, -lane '$F[0]="new"; print join ",", @F[0,2..$#F]'
    new,field3
    
    • 4
  3. technomage
    2021-08-27T14:12:58+08:002021-08-27T14:12:58+08:00

    Reescrever $0 com gensubpode resultar em scripts mais simples.

    Para remover os campos 2 e 3 de uma determinada entrada, você pode remover os campos de $0 usando gensube regenerar $0 (e, portanto, todos os campos) da seguinte maneira:

    > echo 'field1,field2,field3' \
        | awk -F, '{OFS=","; \
                    transform($1); \
                    $0=gensub(/[^,]*,/,"",2); \
                    print}'
    new_field1,field3
    

    Note que printé equivalente a print $0.

    • 1

relate perguntas

  • remova o número de linhas duplicadas com base na correspondência antes da primeira vírgula

  • anexar linhas após outros arquivos linha por linha

  • Como remover uma única linha entre duas linhas

  • Reorganize as letras e compare duas palavras

  • Embaralhamento de arquivo de várias linhas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve