Shell = Verificar si la variable comienza con #

16

Le agradecería que me ayudara a descubrir cómo determinar si el contenido de una variable comienza con el signo hash:

#!bin/sh    

myvar="#comment asfasfasdf"

if [ myvar = #* ] 

esto no funciona.

¡Gracias!

Jans

ene
fuente
1
Consideraría la posibilidad de que también haya espacios antes de la etiqueta hash al probar "comentarios", si eso es lo que está haciendo.
rthomson
Como aceptó una respuesta que involucra una bashsolución, tal vez podría editar su pregunta, ya que implica que desea una solución sh/ dash.
Charles Roberto Canato
Recomiendo usar una ruta absoluta en la #!línea como una ruta relativa en esa línea aparentemente se toma en relación con el directorio actual del proceso que ejecuta la secuencia de comandos en lugar de en relación con la ubicación de la secuencia de comandos.
kasperd

Respuestas:

20

Su enfoque original funcionaría bien si escapó del hash :

$ [[ '#snort' == \#* ]]; echo $?
0

Otro enfoque sería cortar el primer carácter del contenido de la variable, usando "Expansión de subcadena":

if [[ ${x:0:1} == '#' ]]
then
    echo 'yep'
else
    echo 'nope'
fi

yep

Desde la página de manual de Bash:

   ${parameter:offset}
   ${parameter:offset:length}
          Substring  Expansion.   Expands  to  up  to length characters of
          parameter starting at the character  specified  by  offset.   If
          length  is omitted, expands to the substring of parameter start-
          ing at the character specified by offset.  length and offset are
          arithmetic   expressions   (see  ARITHMETIC  EVALUATION  below).
          length must evaluate to a number greater than or equal to  zero.
          If  offset  evaluates  to  a number less than zero, the value is
          used as an offset from the end of the value  of  parameter.   If
          parameter  is  @,  the  result  is  length positional parameters
          beginning at offset.  If parameter is an array name indexed by @
          or  *,  the  result is the length members of the array beginning
          with ${parameter[offset]}.  A negative offset is taken  relative
          to  one  greater  than the maximum index of the specified array.
          Note that a negative offset must be separated from the colon  by
          at  least  one  space to avoid being confused with the :- expan-
          sion.  Substring indexing is zero-based  unless  the  positional
          parameters are used, in which case the indexing starts at 1.
Insyte
fuente
Para ver esta página de manual, debo escribir man what?
duleshi
Es la página de manual de Bash, así que " man bash" debería hacerlo.
Insyte
2
Eso es bashism, pero la etiqueta es sobre "shell" no "bash" :(.
pevik
11

Versión compatible con POSIX:

[ "${var%${var#?}}"x = '#x' ] && echo yes

o:

[ "${var#\#}"x != "${var}x" ] && echo yes

o:

case "$var" in
    \#*) echo yes ;;
    *) echo no ;;
esac
Kambus
fuente
1
+1 para la respuesta posix. En algunas pruebas de tiempo rudimentarias, el casemétodo parece ser el más rápido de los tres en una computadora x86 de 32 bits bastante antigua. Los tres son mucho más eficiente que un ejemplo sencillo que las tuberías a un procesador de entrada estándar en forma de horquilla como: echo $var | cut -c1. Mi análisis fue bastante básico basado en 10,000,000 iteraciones en una sola computadora / os - YMMV. Acabo de usar esa computadora más lenta para exagerar las diferencias y hacerlas más visibles, al menos en esa plataforma.
Juan
Por cierto, para esas 10,000,000 iteraciones, los métodos incorporados descritos en esta respuesta se ejecutaron en aproximadamente un minuto (en el cuadro lento mencionado anteriormente). La pipa al cutsabor tomó más de 5 horas.
Juan
¿Qué pasa si quieres encontrar cosas que comienzan con "
Justin
5

Sé que esto puede ser herejía, pero para este tipo de cosas prefiero usar grep o egrep en lugar de hacerlo desde dentro del shell. Es un poco más costoso (supongo), pero para mí la legibilidad de esta solución compensa eso. Sin embargo, es una cuestión de gusto personal, por supuesto.

Entonces:

myvar="   #comment asfasfasdf"
if ! echo $myvar | egrep -q '^ *#'
then
  echo "not a comment"
else
  echo "commented out"
fi

Funciona con o sin espacios iniciales. Si desea dar cuenta de las pestañas principales también, utilizar egrep q '^ [\ t] * #' en su lugar.

Eduardo Ivanec
fuente
Pensando en ello, tal vez prefiera egrep porque me gustan las expresiones regulares, pero considero que grep / egrep es útil en una gama más amplia de situaciones de todos modos.
Eduardo Ivanec
0

Aquí hay otra forma ...

# assign to var the value of argument actual invocation
var=${1-"#default string"}

if [[ "$var" == "#"* ]]
then
  echo "$var starts with a #"
fi

Simplemente copiar y pegar el contenido de un archivo, conceder permisos de ejecución, y ver cómo se trabaja solo;).

¡Espero eso ayude!

Saludos.

Víctor
fuente
1
Eso es bashism, pero la etiqueta es sobre "shell" no "bash" :(.
pevik