Shell = Sprawdź, czy zmienna zaczyna się od #

16

byłbym wdzięczny, gdybyś mógł mi pomóc dowiedzieć się, jak ustalić, czy zawartość zmiennej zaczyna się od znaku skrótu:

#!bin/sh    

myvar="#comment asfasfasdf"

if [ myvar = #* ] 

to nie działa.

Dzięki!

Jans

Jan
źródło
1
Zastanawiałbym się nad możliwością spacji przed znacznikiem skrótu również podczas testowania pod kątem „komentarzy”, jeśli rzeczywiście tak robisz.
rthomson
Gdy zaakceptowałeś odpowiedź dotyczącą bashrozwiązania, być może mógłbyś edytować swoje pytanie, ponieważ oznacza to, że pragniesz rozwiązania sh/ dash.
Charles Roberto Canato,
Polecam użycie bezwzględnej ścieżki w #!linii, ponieważ ścieżka względna w tej linii jest najwyraźniej pobierana w odniesieniu do bieżącego katalogu procesu wykonującego skrypt, a nie do położenia skryptu.
kasperd,

Odpowiedzi:

20

Twoje oryginalne podejście sprawdziłoby się dobrze, gdybyś uniknął skrótu :

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

Innym podejściem byłoby wycięcie pierwszego znaku zawartości zmiennej przy użyciu „rozszerzenia ciągu znaków”:

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

yep

Ze strony podręcznika użytkownika 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
źródło
Aby zobaczyć tę stronę podręcznika, powinienem wpisać man co?
duleshi
To jest strona podręcznika użytkownika Bash, więc man bashnależy to zrobić.
Insyte
2
To jest bashism, ale tag dotyczy „shell”, a nie „bash” :(.
pevik
11

Wersja kompatybilna z POSIX:

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

lub:

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

lub:

case "$var" in
    \#*) echo yes ;;
    *) echo no ;;
esac
Kambus
źródło
1
+1 za odpowiedź na posix. W niektórych podstawowych testach czasowych casemetoda wydaje się najszybsza z trzech na dość starym 32-bitowym komputerze x86. Wszystkie trzy są znacznie bardziej skuteczne niż zwykłe np które to rury do rozwidlonych standardowego wejścia procesora typu: echo $var | cut -c1. Moja analiza była dość podstawowa w oparciu o 10 000 000 iteracji na jednym komputerze / systemie operacyjnym - YMMV. Właśnie użyłem tego wolniejszego komputera, aby wyolbrzymić różnice i uczynić je bardziej widocznymi - przynajmniej na tej jednej platformie.
Juan
BTW, dla tych 10 000 000 iteracji wbudowane metody opisane w tej odpowiedzi działały w ciągu około minuty (na wspomnianym wolnym polu). Fajka do cutsmaku trwała ponad 5 godzin.
Juan
Co jeśli chcesz znaleźć rzeczy zaczynające się od „
Justin
5

Wiem, że to może być herezja, ale do tego rodzaju rzeczy wolałbym używać grep lub egrep, zamiast robić to z poziomu powłoki. Jest to trochę bardziej kosztowne (tak sądzę), ale dla mnie czytelność tego rozwiązania to równoważy. Oczywiście jest to kwestia osobistego gustu.

Więc:

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

Działa z wiodącymi spacjami lub bez nich. Jeśli chcesz także uwzględnić wiodące karty, użyj zamiast tego egrep -q '^ [\ t] * #'.

Eduardo Ivanec
źródło
Myśląc o tym, może po prostu wolę egrep, ponieważ lubię wyrażenia regularne, ale i tak uważam grep / egrep za przydatne w szerszym zakresie sytuacji.
Eduardo Ivanec
0

Oto inny sposób ...

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

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

Wystarczy skopiować i wkleić zawartość do pliku, udzielić uprawnień do wykonywania i zobaczyć, jak to działa;).

Mam nadzieję, że to pomoże!

Pozdrowienia.

Zwycięzca
źródło
1
To jest bashism, ale tag dotyczy „shell”, a nie „bash” :(.
pevik