web-dev-qa-db-fra.com

Utilisez AWK pour diviser la ligne dans la matrice et utilisez les valeurs de ce tableau en appelant Shell

J'essaie d'utiliser awk à l'intérieur d'un script bash et faites une tâche assez courante: itéréez des lignes de fichiers bien structurées et divisez-les par un délimiteur en une matrice. Voici un échantillon du fichier:

Joe:Johnson:25
Sue:Miller:27

Il existe de nombreux exemples comment cela peut être fait sur une seule ligne au mode interactif, cependant, je le fais dans un script dans lequel j'aimerais utiliser ce tableau manipulé par Awk en dehors du sous-groupe AWK à Bash lui-même:

cat ${smryfile} | while read smryline; do

    echo ${smryline}

    #now i want to split the line into array 'linearray' in awk but have it usable when i get back to bash
    echo ${smryline} | awk '{split($0,$linearray,":")}'

    varX=$linearray[2]
    echo $varX
    #do something with $varX

done

Je reçois une erreur:

awk: syntax error at source line 1
 context is
     >>> {split($0,$linearray <<< ,":")}
awk: illegal statement at source line 1

Est-il possible de faire ce que j'essaie de faire (utilisez des tableaux définis dans Awk en dehors de sa portée) et comment dois-je le faire?

7
amphibient

Je pense que vous pouvez faire ce que vous voulez sans awk:

cat "${smryfile}" | while IFS=: read first last varx
do
    echo "first='$first' last='$last' varx='$varx'"
    # do something
done

Cela produit:

first='Joe' last='Johnson' varx='25'
first='Sue' last='Miller' varx='27'

Notez que cette approche fonctionnera même si certains noms du fichier comprennent des espaces.

Notez également que l'utilisation de cat ci-dessus n'est pas nécessaire:

while IFS=: read first last varx
do
    echo "first='$first' last='$last' varx='$varx'"
    # do something
done <"${smryfile}"

Un avantage latéral de l'élimination de l'élimination cat, selon ce qui précède, est que toutes les variables que vous créez dans la boucle survivront après la finition de la boucle.

7
John1024

Accordé que vous avez demandé une solution avec awk, mais je pense que la solution sed est un peu plus claire.

str="Joe:Johnson:25"
array=($(echo "$str" | sed 's/:/ /g'))
for el in "${array[@]}"; do
    echo "el = $el"
done

Cela donne:

el = Joe
el = Johnson
el = 25

Dans ce cas, vous devez être sûr de ne pas mettre des citations doubles autour de l'expansion de la commande, de sorte que vous ne vous retrouvez pas avec un seul élément de chaîne.

Et cela ne fonctionne pas pour des éléments contenant des espaces, bien sûr. Si tu avais:

str="Joe:Johnson:25:Red Blue"

Tu finis avec

el = Joe
el = Johnson
el = Red
el = Blue

Mais si cela ne vous dérange pas d'utiliser eval, vous pouvez insérer des guillemets avant que l'affectation du tableau pour le faire fonctionner.

eval "array=($(echo "\"$str\"" | sed 's/:/" "/g'))"

# Before the eval, it turns into:
eval "array=("Joe" "Johnson" "25" "Red Blue")"
0
krb686