awk programming - Alterando um valor de campo condicionalmente

4

Sou um iniciante em programação awk. Este post é para esclarecer uma dúvida. Eu tenho arquivo assim:

70 17 5 mb
71 18 6 ms
72 19 7 ml
73 20 8 mw

em que a quarta coluna é uma string. Eu quero fazer alterações na terceira coluna em relação à quarta coluna. Por exemplo: para ler a quarta coluna, se $4=ms , em seguida, $3=$3+1 .

Na verdade eu não sei como fazer o programa ler uma string ms.

Por favor me ajude com relação a isso!

    
por user2519044 26.06.2013 / 08:51

4 respostas

7

Para fazer isso, você precisa usar a instrução condicional dentro do bloco de ações {} .

A sintaxe é if ( expr ) statement

Para corresponder à condição em que a quarta coluna é ms e reatribuir o valor da terceira coluna quando a condição for correspondida:

if ($4 == "ms") $3=$3+1

e imprima a linha inteira usando print $0

O comando completo é assim:

awk '{ if ($4 == "ms") $3=$3+1; print $0 }'

    
por Flint 26.06.2013 / 10:26
6

Se a condição for simples, você pode usar a correspondência de padrões para modificar linhas.

Supondo que test.txt contenha os dados do exemplo:

cat test.txt
70 17 5 mb
71 18 6 ms
72 19 7 ml
73 20 8 mw

Vamos examinar a seguinte linha e sua saída:

awk '/ms$/ {$3++} {print}' test.txt
70 17 5 mb
71 18 7 ms
72 19 7 ml
73 20 8 mw

O comando awk lê o conteúdo de test.txt e executa o script awk /ms$/ {$3++} {print} em cada linha. O script pode ser reescrito como:

/ms$/ {$3++}

      {print}
  • Existem duas ações no script dentro de chaves: {} .
    • O segundo é mais fácil de explicar: apenas imprime toda a linha.
    • O primeiro contém uma especificação de padrão antes da ação. A ação será executada apenas em linhas correspondentes. O padrão é escrito dentro de barras: // .
      • ms$ significa que cada linha com a string ms no final da linha $ (O sinal de cifrão indica que a string deve ser a última da linha).
      • A ação $3++ incrementa o valor da terceira coluna em um.

Por favor, note que a ação {print} será sempre executada, porque não há padrão para esta ação, mas o padrão {$3++} será executado somente se a string "ms" for encontrada no final da linha. Além disso, o incremento acontece antes da impressão, portanto, todas as modificações necessárias serão realizadas no prazo.

    
por lgarzo 26.06.2013 / 11:56
1

Arquivo de entrada:

cat f.txt
70 17 5 mb
71 18 6 ms
72 19 7 ml
73 20 8 mw

Soluções possíveis:

1. awk '$4=="ms",$3=$3+1;{print}' f.txt
70 17 5 mb
71 18 7 ms
71 18 7 ms
72 19 7 ml
73 20 8 mw

(não sei por que, mas não é bom - linha (s) alvo (s) duplicada (s))

2. awk '{if ($4=="ms"){$3=$3+1}; print}' f.txt
70 17 5 mb
71 18 7 ms
72 19 7 ml
73 20 8 mw

( funcionou como esperado )

3. awk '{if ($4=="ms"){$3=$3+1} print}' f.txt
70 17 5 mb
71 18 7 ms
72 19 7 ml
73 20 8 mw

( ponto-e-vírgula "; " não é necessário )

4. awk '{if ($4=="ms"){$3=$3+1} else {$3=$3/2}; print}' f.txt
70 17 2.5 mb
71 18 7 ms
72 19 3.5 ml
73 20 4 mw

( funcionou como esperado e mais ... )

5. awk '{if ($4=="ms"){$3=$3+1} else {$3=$3/2} print}' f.txt
70 17 2.5 mb
71 18 7 ms
72 19 3.5 ml
73 20 4 mw

( ponto e vírgula "; " é dispensável )

    
por VXtal 09.01.2017 / 12:04
0

OP respondeu à sua própria pergunta, quando descreveram as condições. Deveria ter sido traduzido assim:

$ awk '$4=="ms"{$3=$3+1};1' input.txt                  
70 17 5 mb
71 18 7 ms
72 19 7 ml
73 20 8 mw

A expressão antes de {} no awk é tratada como if , portanto funciona da mesma forma que OP perguntou: se $ 4 for "ms", incremente $ 3. O 1 após o {}; significa simplesmente print . A sequência também é importante, porque verificamos as condições primeiro e depois imprimimos.

Como alternativa à abordagem awk, o python também pode fazê-lo. O pequeno roteiro abaixo pode fazer o trabalho. Ele também pode ser transformado em uma linha, mas para facilitar a leitura, estou fornecendo apenas o script aqui

#!/usr/bin/env python
from __future__ import print_function
import sys

with open(sys.argv[1]) as f:
     for line in f:
          words = line.strip().split()
          if words[3] == "ms":
             words[2] = str(int(words[2]) + 1)
          print(" ".join(words))

E a execução da amostra:

$ ./increment_field.py input.txt                                                                                  
70 17 5 mb
71 18 7 ms
72 19 7 ml
73 20 8 mw
    
por Sergiy Kolodyazhnyy 09.01.2017 / 12:31

Tags