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


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.

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

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] * #'.


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.


1
To jest bashism, ale tag dotyczy „shell”, a nie „bash” :(.
— pevik
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.