Domanda

Trovo AWK davvero utile. Ecco un esempio che ho messo insieme per manipolare i dati.

ls | awk '{ print "awk " "'"'"'"  " {print $1,$2,$3} " "'"'"'"  " " $1 ".old_ext > " $1    ".new_ext"  }' > file.csh

Ho usato questo AWK per creare un file di script che rinominasse alcuni file e stampasse solo colonne selettive. Qualcuno sa un modo migliore per farlo? Quali sono i tuoi migliori rivestimenti AWK o manipolazioni intelligenti?

È stato utile?

Soluzione

Il AWK book è pieno di grandi esempi. In passato venivano raccolti per il download dalla la pagina web di Kernighan (404s ora).

Altri suggerimenti

Puoi trovare diverse belle linee qui .

Uso questo:

df -m | awk '{p+=$3}; END {print p}'

Per sommare tutto lo spazio su disco utilizzato su un sistema attraverso filesystem.

Molti anni fa ho scritto un copione di coda in awk:

#!/usr/bin/awk -f
BEGIN {
  lines=10
}

{
  high = NR % lines + 1
  a[high] = <*>
}

END {
  for (i = 0; i < lines; i++) {
    n = (i + high) % lines + 1
    if (n in a) {
      print a[n]
    }
  }
}

Lo so, è sciocco, ma è quello che Awk ti fa. È molto divertente giocarci.

Henry Spencer ha scritto un'implementazione abbastanza buona di nroff su awk. Lo chiamò "awf". Ha anche affermato che se Larry Wall avesse saputo quanto fosse potente Awk, non avrebbe avuto bisogno di inventare Perl.

Ecco un paio di awk che usavo regolarmente ... nota che puoi usare $ 1, $ 2, ecc. per uscire dalla colonna che desideri. Quindi, per manipolare un mucchio di file, ad esempio ecco uno stupido comando che potresti usare al posto di mv ...

ls -1 *.mp3 | awk '{printf("mv %s newDir/%s\n",$1,$1)}' | /bin/sh

O se stai osservando una serie di processi forse ...

ps -ef | grep -v username | awk '{printf("kill -9 %s\n",$2)}' | /bin/sh

Abbastanza banale ma puoi vedere come ciò ti farebbe guadagnare un bel po 'di modi. =) La maggior parte delle cose che facevo per te può usare xargs, ma hey, chi ha bisogno di loro nuovi comandi confusi?

Uso questo script molto per la modifica di PATH e variabili d'ambiente tipo path. Uso:

export PATH=$(clnpath /new/bin:/other/bin:$PATH /old/bin:/other/old/bin)

Questo comando aggiunge / new / bin e / other / bin davanti a PATH, rimuove entrambi / old / bin e / other / old / bin da PATH (se presente - nessun errore se assente) e rimuove voci di directory duplicate sul percorso.

:   "@(#)$Id: clnpath.sh,v 1.6 1999/06/08 23:34:07 jleffler Exp <*>quot;
#
#   Print minimal version of $PATH, possibly removing some items

case $# in
0)  chop=""; path=${PATH:?};;
1)  chop=""; path=$1;;
2)  chop=$2; path=$1;;
*)  echo "Usage: `basename <*> .sh` [$PATH [remove:list]]" >&2
    exit 1;;
esac

# Beware of the quotes in the assignment to chop!
echo "$path" |
${AWK:-awk} -F: '#
BEGIN       {       # Sort out which path components to omit
                    chop="'"$chop"'";
                    if (chop != "") nr = split(chop, remove); else nr = 0;
                    for (i = 1; i <= nr; i++)
                            omit[remove[i]] = 1;
            }
{
    for (i = 1; i <= NF; i++)
    {
            x=$i;
            if (x == "") x = ".";
            if (omit[x] == 0 && path[x]++ == 0)
            {
                    output = output pad x;
                    pad = ":";
            }
    }
    print output;
}'

Conta la memoria utilizzata da httpd

ps -ylC httpd | awk '/[0-9]/ {SUM += $8} END {print SUM/1024}'

O qualsiasi altro processo sostituendo httpd. Divisione per 1024 per ottenere output in MB.

Sono riuscito a creare un emulatore di comandi dell'albero DOS per UNIX (find + awk):

find . -type d -print 2>/dev/null|awk '{for (i=1;i< NF;i++)printf("%"length($i)"s","|");gsub(/[^\/]*\//,"--",<*>);print $NF}'  FS='/'

Stampa le linee tra due motivi:

awk '/END/{flag=0}flag;/START/{flag=1}' inputFile

Spiegazione dettagliata: http://nixtip.wordpress.com/2010/10/12/print-lines-between-two-patterns-the-awk-way/

Un paio di preferiti, essenzialmente non correlati tra loro. Leggi come 2 diversi suggerimenti non collegati.

Identificazione semplice dei numeri di colonna

Per quelli che usano frequentemente awk, come faccio per l'analisi dei log al lavoro, mi trovo spesso a dover scoprire quali sono i numeri di colonna per un file. Quindi, se sto analizzando, diciamo, i file di accesso ad Apache (alcuni esempi sono disponibili qui ) Eseguo lo script seguente sul file:

NR == 1 {
        for (i = 1 ; i <= NF ; i++)
                {
                print i "\t" $i
                }
        }
NR > 1  {
        exit
        }

In genere lo chiamo " cn.awk " ;, per "c'olumn" n'umbers. Creativo, eh? Ad ogni modo, l'output è simile a:

1   64.242.88.10
2   -
3   -
4   [07/Mar/2004:16:05:49
5   -0800]
6   "GET
7   /twiki/bin/edit/Main/Double_bounce_sender?topicparent=Main.ConfigurationVariables
8   HTTP/1.1"
9   401
10  12846

Molto facile dire cosa sia cosa. Di solito lo alias sui miei server e ce l'ho dappertutto.


Campi di riferimento per nome

Ora, supponi che il tuo file abbia una riga di intestazione e preferiresti usare quei nomi invece dei numeri di campo. Ciò ti consente di farlo:

NR == 1 {
    for (i = 1 ; i <= NF ; i++)
        {
        field[$i] = i
        }
    }

Ora, supponiamo che io abbia questa riga di intestazione ...

metrica, tempo, val, posizione, HTTP_STATUS, http_request

... e vorrei sommare la colonna val . Invece di fare riferimento a $ 3, posso fare riferimento ad esso per nome:

NR > 1  {
    SUM += $field["val"]
    }

Il vantaggio principale è rendere lo script molto più leggibile.

La stampa dei campi è una delle prime cose menzionate nella maggior parte dei tutorial di AWK.

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

Meno conosciuti ma ugualmente utili è l'esclusione di campi che è anche possibile:

awk '{$1=$3=""}1' file
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top