2011-06-27 8 views
8

Al reemplazar comandos externos en un script de shell, utilicé una matriz para deshacerme de awk's NF.¿Cómo marcar una matriz en POSIX sh?

Ahora, desde que me mudé de bash para POSIX sh, no puedo obtener la matriz marcada derecha:

#!/bin/bash 
export RANGE="0 1 4 6 8 16 24 46 53" 
RANGE=($RANGE) 
echo arrayelements: $((${#RANGE[@]})) 
LAST=$((${#RANGE[@]}-1)) 
echo "Last element(replace NF): ${RANGE[$LAST]}" 

# ./foo 
arrayelements: 9 
Last element(replace NF): 53 

estoy usando OpenBSD, SH y tiene exactamente el mismo tamaño que el ksh. Cambio de arriba para /bin/sh, parece que el siguiente no funciona:

set -A "$RANGE" 
set -- "$RANGE" 

¿Cómo podría darse cuenta de que el guión acaba en /bin/sh? (Tenga en cuenta que funciona bien si invoca bash con --posix, eso no es lo que busco)

+1

Aparte: los nombres de las mayúsculas son de mala calidad. Consulte las convenciones para nombres de variables de entorno en http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html, cuarto párrafo, teniendo en cuenta que las variables de entorno y las variables de shell comparten un espacio de nombres, por lo que se utilizan nombres de minúsculas sus variables locales evitarán que se sobrescriba accidentalmente algo con significado para el sistema. –

Respuesta

12

Las matrices no son parte de POSIX sh specification.

Existen otras formas de encontrar el último elemento. Un par de posibilidades:

#!/bin/sh 
export RANGE="0 1 4 6 8 16 24 46 53" 
for LAST_ITEM in $RANGE; do true; done 
echo "Last element(replace NF): $LAST_ITEM" 

o:

#!/bin/sh 
export RANGE="0 1 4 6 8 16 24 46 53" 
LAST_ITEM="${RANGE##* }" 
echo "Last element(replace NF): $LAST_ITEM" 
+0

han pasado 5 años. ¿Cualquier actualización? –

1

El siguiente código funciona para mí utilizando el Heirloom Bourne Shell:

#!/usr/local/bin/bournesh 
# cf. Heirloom Bourne Shell, 
#  http://freshmeat.net/projects/bournesh/ 
#  http://www.in-ulm.de/~mascheck/bourne/ 

# use a caret as a pipe symbol to make sure it's a Bourne shell 
# cf. http://mywiki.wooledge.org/BourneShell 
ls^cat 1>/dev/null 2>&1 || 
    { echo 'No true Bourne shell! ... exiting ...'; exit 1; } 

IFS=' ' 
unset RANGE 
RANGE="0 1 4 6 8 16 24 46 53" 
export IFS RANGE 
set -- $RANGE 
echo arrayelements: $# 
LAST=$# 
eval echo "Last element\(replace NF\): \$$#" 

Tenga en cuenta que IFS se establece en un espacio y no existen comillas dobles alrededor de $RANGE.

+2

Esto solo funciona para elementos que no contienen espacios en blanco. El objetivo de tener una matriz en tu caparazón es permitir tales elementos. – chepner

2

Puede utilizar el siguiente proyecto de Github, que implementa una matriz compatible con POSIX, que funciona en todas las conchas que probé: https://github.com/makefu/array

No es muy cómodo de usar, pero me pareció que funcione bien para mis propósitos