Comment diviser la chaîne lorsqu'elle contient des symboles de canal |
. Je veux les séparer pour être dans le tableau.
J'ai essayé
echo "12:23:11" | awk '{split($0,a,":"); print a[3] a[2] a[1]}'
Ce qui fonctionne bien. Si ma chaîne ressemble à "12|23|11"
alors comment puis-je les diviser en un tableau?
As-tu essayé:
echo "12|23|11" | awk '{split($0,a,"|"); print a[3],a[2],a[1]}'
Pour scinder une chaîne en un tableau dans awk
, nous utilisons la fonction split()
:
awk '{split($0, a, ":")}'
# ^^ ^ ^^^
# | | |
# string | delimiter
# |
# array to store the pieces
Si aucun séparateur n'est donné, il utilise la variable FS
, qui prend par défaut l'espace:
$ awk '{split($0, a); print a[2]}' <<< "a:b c:d e"
c:d
Nous pouvons donner un séparateur, par exemple :
:
$ awk '{split($0, a, ":"); print a[2]}' <<< "a:b c:d e"
b c
Ce qui équivaut à le définir via la FS
:
$ awk -F: '{split($0, a); print a[1]}' <<< "a:b c:d e"
b c
Dans gawk, vous pouvez également fournir le séparateur sous forme d'expressions rationnelles:
$ awk '{split($0, a, ":*"); print a[2]}' <<< "a:::b c::d e" #note multiple :
b c
Et même voir ce que le délimiteur était sur chaque étape en utilisant son quatrième paramètre:
$ awk '{split($0, a, ":*", sep); print a[2]; print sep[1]}' <<< "a:::b c::d e"
b c
:::
Citons la page de manuel de GNU awk :
split (chaîne, tableau [ champsep [ seps]])
Divisez la chaîne en morceaux séparés par fieldsep et stockez les morceaux dans tableau et les chaînes de séparation dans le tableau seps . Le premier morceau est stocké dans
array[1]
, le deuxième morceau dansarray[2]
, et ainsi de suite. La valeur de chaîne du troisième argument, fieldsep , est une expression rationnelle décrivant le lieu de division de la chaîne (un peu comme FS peut être une expression rationnelle décrivant le lieu de fractionnement des 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 une extensiongawk
, avecseps[i]
représentant la chaîne de séparation entrearray[i]
etarray[i+1]
. Si fieldsep est un espace unique, alors tout espace au début est placé dansseps[0]
et tout espace à la fin passe àseps[n]
, où n est la valeur de retour desplit()
(c'est-à-dire le nombre d'éléments dans un tableau).
S'il vous plaît être plus précis! Que voulez-vous dire par "ça ne marche pas"? Publiez la sortie exacte (ou le message d'erreur), votre version du système d'exploitation et awk:
% awk -F\| '{
for (i = 0; ++i <= NF;)
print i, $i
}' <<<'12|23|11'
1 12
2 23
3 11
Ou, en utilisant split:
% awk '{
n = split($0, t, "|")
for (i = 0; ++i <= n;)
print i, t[i]
}' <<<'12|23|11'
1 12
2 23
3 11
Edit: on Solaris vous aurez besoin d'utiliser POSIX awk (/ usr/xpg4/bin/awk) pour traiter 4000 champs correctement.
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
En fait, awk
possède une fonctionnalité appelée 'Variable de séparation de champ de saisie' lien . Voici comment l'utiliser. Ce n'est pas vraiment un tableau, mais il utilise les variables internes $. Pour fendre une chaîne simple, c'est plus facile.
echo "12|23|11" | awk 'BEGIN {FS="|";} { print $1, $2, $3 }'
Je n'aime pas la solution echo "..." | awk ...
car elle appelle des appels inutiles fork
et exec
system.
Je préfère une solution de Dimitre avec un peu de torsion
awk -F\| '{print $3 $2 $1}' <<<'12|23|11'
Ou version un peu plus courte:
awk -F\| '$0=$3 $2 $1' <<<'12|23|11'
Dans ce cas, l'enregistrement de sortie mis en place est une condition vraie, il est donc imprimé.
Dans ce cas spécifique, la redirection stdin
peut être épargnée avec le paramétrage d'une variable interne awk :
awk -v T='12|23|11' 'BEGIN{split(T,a,"|");print a[3] a[2] a[1]}'
J'ai utilisé ksh assez longtemps, mais dans bash , cela pourrait être géré par une manipulation interne de chaîne. Dans le premier cas, la chaîne d'origine 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 de 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
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
devrait marcher.
Blague? :)
Que diriez-vous de echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
Ceci est ma sortie:
p2> echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
112312
donc je suppose que ça marche après tout ..