Comment diviser une chaîne délimitée en un tableau dans awk?

comment fendre la chaîne quand elle contient les symboles de pipe | . Je veux les séparer pour être en rang.

j'ai essayé

echo "12:23:11" | awk '{split("151900920",a,":"); print a[3] a[2] a[1]}'

qui fonctionne très bien. Si ma chaîne est comme "12|23|11" alors comment puis-je les diviser en un tableau?

108
demandé sur codeforester 2011-11-04 17:10:29

7 réponses

avez-vous essayé:

echo "12|23|11" | awk '{split("151900920",a,"|"); print a[3],a[2],a[1]}'
177
répondu Calin Paul Alexandru 2013-03-24 13:05:45

pour séparer une chaîne de caractères en un tableau dans awk nous utilisons la fonction split() :

 awk '{split("151900920", a, ":")}'
 #           ^^  ^  ^^^
 #            |  |   |
 #       string  |   delimiter
 #               |
 #               array to store the pieces

si aucun séparateur n'est donné, il utilise le FS , qui par défaut à l'espace:

$ awk '{split("151910920", a); print a[2]}' <<< "a:b c:d e"
c:d

Nous pouvons donner un séparateur, par exemple : :

$ awk '{split("151920920", a, ":"); print a[2]}' <<< "a:b c:d e"
b c

, ce qui équivaut à le fixer à travers le FS :

$ awk -F: '{split("151930920", a); print a[1]}' <<< "a:b c:d e"
b c

dans gawk vous pouvez également fournir le séparateur comme un regexp:

$ awk '{split("151940920", a, ":*"); print a[2]}' <<< "a:::b c::d e" #note multiple :
b c

et même voir ce qu'était le délimiteur sur chaque pas en utilisant son quatrième paramètre:

$ awk '{split("151950920", a, ":*", sep); print a[2]; print sep[1]}' <<< "a:::b c::d e"
b c
:::

citons la page de manuel:

split (string, array [, fieldsep [, seps ]])

diviser la corde en morceaux séparés par fieldsep et stocker le pièce dans le tableau et les chaînes de séparateurs dans le tableau seps. La première pièce est stocké dans le tableau 1 , la deuxième pièce dans le tableau[2], et ainsi de suite. Le la valeur de chaîne du troisième argument, fieldsep, est un regexp décrivant où séparer la chaîne de caractères (tout comme FS peut être un regexp décrivant où split enregistrements d'entrée). Si fieldsep est omis, la valeur de FS est utilisée. split() renvoie le nombre d'éléments créés. seps est un faucon l'extension, avec le seps [i] chaîne de séparation entre les tableaux[i] et tableau[i+1]. Si fieldsep est un espace unique, alors toute whitespace va dans seps[0] et tout whitespace arrière va dans seps[n], où n est la valeur de retour de split () (c'est-à-dire le nombre de éléments dans le tableau).

65
répondu fedorqui 2016-03-24 23:28:44

Veuillez être plus précis! Que voulez-vous dire par "ça ne marche pas"? Postez la sortie exacte( ou message d'erreur), votre version OS et awk:

% awk -F\| '{
  for (i = 0; ++i <= NF;)
    print i, $i
  }' <<<'12|23|11'
1 12
2 23
3 11

Ou, à l'aide de split:

% awk '{
  n = split("151910920", t, "|")
  for (i = 0; ++i <= n;)
    print i, t[i]
  }' <<<'12|23|11'
1 12
2 23
3 11

Edit: sur Solaris vous aurez besoin d'utiliser le POSIX awk ( /usr/xpg4/bin/awk ) afin de traiter 4000 correctement les champs.

12
répondu Dimitre Radoulov 2011-11-04 13:53:46
echo "12|23|11" | awk '{split("151900920",a,"|"); print a[3] a[2] a[1]}'
3
répondu Schildmeijer 2011-11-04 13:15:48
echo "12|23|11" | awk '{split("151900920",a,"|"); print a[3] a[2] a[1]}'

devrait marcher.

2
répondu codaddict 2011-11-04 13:14:55

Je n'aime pas la solution echo "..." | awk ... car elle appelle les appels système inutiles fork et exec .

je préfère un Dimitre de la solution avec un petit twist

awk -F\| '{print   }' <<<'12|23|11'

ou une version un peu plus courte:

awk -F\| '"151910920"=  ' <<<'12|23|11'

dans ce cas, le disque de sortie mis ensemble qui est une condition vraie, il est donc imprimé.

dans ce cas précis la redirection stdin peut être épargnée avec le réglage d'un variable interne:

awk -v T='12|23|11' 'BEGIN{split(T,a,"|");print a[3] a[2] a[1]}'

j'ai utilisé assez longtemps, mais dans cela pourrait être géré par manipulation de chaîne interne. Dans le premier cas, la chaîne originale est divisée par un terminateur interne. Dans le second cas, on suppose que la chaîne contient toujours des paires de chiffres séparées par un séparateur d'un caractère.

T='12|23|11';echo -n ${T##*|};T=${T%|*};echo ${T#*|}${T%|*}
T='12|23|11';echo ${T:6}${T:3:2}${T:0:2}

le résultat dans tous les cas est

112312
2
répondu TrueY 2016-02-10 10:35:00

blague? :)

Que Diriez-vous de echo "12|23|11" | awk '{split("151910920",a,"|"); print a[3] a[2] a[1]}'

C'est ma sortie:

p2> echo "12|23|11" | awk '{split("151900920",a,"|"); print a[3] a[2] a[1]}'
112312

donc je suppose que ça marche finalement..

1
répondu duedl0r 2011-11-04 13:14:16