web-dev-qa-db-fra.com

conserver les espaces blancs dans les champs lors de l'utilisation de awk

J'utilise nawk sur un fichier délimité par des tuyaux pour imprimer les champs comme index et clé où certains champs contiennent des espaces blancs, quand il n'y a pas d'espace blanc, tout fonctionne normalement, mais dans le cas d'espaces blancs en quelque sorte awk le traite comme séparateur de champs et imprime cet o/p à la nouvelle ligne. Voir mon entrée ci-dessous:

Contribution:

a|b|c d e|1|2|3
a|b c|d|1|2|2 3

Production:

Index=a|b|c 
Key=1|2|3
Index=d
Key=<null>
Index=e
Key=<null>
Index=a|b
Key=1|2|2
Index=c|d
Key=3

Production attendue:

Index=a|b|c d e
Key=1|2|3
Index=a|b c|d
Key=1|2|2 3

Bref pour deux index 2 index et 2 touches et garder les espaces blancs de base tels quels.

Je dois utiliser l'ensemble de code ci-dessous pour travailler sur chaque ligne car il y a trop de champs et des données énormes

    index=`echo "$line" | nawk -F '|' '
    function select_from(from,to,delim)
    {
            if (to < from) { return; };
            for (i=from;i<=to;i++)
            {
                            if (NF < i) { break;};
                            if (i < to)
                            {
                                    printf("%s%s",i,delim);
                            } else {
                                    printf("%s",i);
                            };
            };
    }
    {select_from(11,48,"|");};'`

les réponses sont correctes lorsque vous utilisez un caractère spécial au lieu de l'espace, mais ce n'est pas correct sur les données d'entrée. alors je veux savoir si je peux conserver de l'espace dans ce processus.

1
leArned

Utilisation de awk

from=1; to=3; delimiter="|"; awk -F"$delimiter" -v from="$from" -v to="$to" '!/^[[:blank:]]*$/ {printf "Index="; for(i=from; i<=to; i++) {printf $i; if(i<to) {printf "|"};} printf "\n"; printf "Key="; for(i=to+1; i<=NF; i++) {printf $i; if(i<NF) {printf "|"};} printf "\n"}' foo

Plus lisible

from=1; to=3; delimiter="|";
awk -F"$delimiter" -v from="$from" -v to="$to" '!/^[[:blank:]]*$/ {
    printf "Index=";
    for(i=from; i<=to; i++) {
        printf $i;
        if(i<to) {
            printf "|"
        };
    }
    printf "\n";
    printf "Key=";
    for(i=to+1; i<=NF; i++) {
        printf $i;
        if(i<NF) {
            printf "|"
        };
    }
    printf "\n"
}' foo

Exemple

$ cat foo
a|b|c d e|1|2|3
a|b c|d|1|2|2 3

$ from=1; to=3; delimiter="|"; awk -F"$delimiter" -v from="$from" -v to="$to" '!/^[[:blank:]]*$/ {printf "Index="; for(i=from; i<=to; i++) {printf $i; if(i<to) {printf "|"};} printf "\n"; printf "Key="; for(i=to+1; i<=NF; i++) {printf $i; if(i<NF) {printf "|"};} printf "\n"}' foo
Index=a|b|c d e
Key=1|2|3
Index=a|b c|d
Key=1|2|2 3
2
A.B.

Vous pouvez utiliser cette commande Perl pour obtenir la sortie attendue:

$ Perl -ne 'print "Index=$1\nKey=$2\n" if /(.*?)[\s\|]([\|\d ]+)/' my_file
Index=a|b|c d e
Key=1|2|3
Index=a|b c|d
Key=1|2|2 3

Je n'utiliserais pas [nmg]awk pour cette tâche. Puisque votre script principal semble être écrit en bash, remplacez simplement votre commande nawk:

#!/bin/bash

Perl -ne 'print "Index=$1\nKey=$2\n" if /(.*?)[\s\|]([\|\d ]+)/' my_file

Notez que vous pouvez également supprimer la boucle créant $line dans votre script d'origine.

1
Sylvain Pineau

Créez un fichier et enregistrez-y le script awk:

#!/usr/bin/awk -f

BEGIN { FS="|";} 
{ 
  printf"Index:";
  for(i=1;i<=NF;i++) {
       if ($i~/[[:alpha:]]/ && $(i+1)!~/[[:digit:]]/) { printf $i"|";
    }
    else if ($i~/[[:alpha:]]/ && $(i+1)~/[[:digit:]]/) {
    print $i
    }
  }

printf "\n"
} 


{ 
  printf"Key=:";
  for(i=1;i<=NF;i++) {
     if ($i~/[[:digit:]]/ && $(i+1)~/[[:digit:]]/) printf $i"|" ;
    else if ($i~/[[:digit:]]$/)  printf $i;

    }
printf "\n"
}  

Enregistrez le fichier, exécutez Sudo chmod +x awk-script-name.awk, et exécutez-le avec le fichier de test comme ceci:

$ cat testfile.txt                                                                                                                    
a|b|c d e|1|2|3
a|b c|d|1|2|2 3

$ key-index-script.awk testfile.txt                                                                                                   
Index:a|b|c d e

Key=:1|2|3
Index:a|b c|d

Key=:1|2|2 3
0