Jak poprawnie uciec wykrzyknikom w bash?

11

Dzisiaj zostałem przyłapany na gorącym uczynku podczas próby kodowania golfa jako generatora haseł na Twitterze.

import string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))

90 znaków. Ponieważ jest to dużo wolnego miejsca, postanowiłem podnieść poprzeczkę i uczynić ją również wykonalną.

echo -e "#!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg

139 znaków. Fajnie, z wyjątkiem oczywiście dławienia się wykrzyknikiem.

badp@delta:~$ echo -e "#!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg
bash: !/usr/bin/python\nimport: event not found

Pesky wykrzyknik. „Chodźmy stąd” - pomyślałem! W końcu mam jedną wolną postać.

echo -e "#\!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg

Oczywiście...

badp@delta:~$ echo -e "#\!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg
./pg: line 2: syntax error near unexpected token `('
./pg: line 2: `import string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))'
badp@delta:~$ cat pg
#\!/usr/bin/python
import string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))

Odkładając na bok mój kod asinine golfa - nie potrafię tego wyjaśnić.

Z \!wykrzyknikiem udało się uciec, ale tak naprawdę nie było, ponieważ \!pozostawiono go echodo odebrania.

\x21Zamiast tego można było zastosować jedno rozwiązanie , ale nie jestem przekonany, że to właściwy sposób na uniknięcie wykrzyknika w poleceniu bash.

tl; dr: Jak właściwie uciec od wykrzyknika w poleceniu bash?

badp
źródło
Czy ktoś faktycznie korzysta ze !eventskładni? Zawsze sprawiało mi to tylko kłopoty.
badp
Używam go prawie codziennie (przez większość ostatnich 20 lat) !:0 !$i !^oszczędzam tyle czasu i pisania.
Alexx Roche

Odpowiedzi:

7

Użyj pojedynczych cytatów:

echo -e '#!/usr/bin/python\nimport string as s,random;print "".join(random.sample(s.letters+s.digits+s.punctuation,9))'>pg;chmod +x pg;./pg

Reguły !zostały później wszczepione w inne reguły cytowania (z csh). Były bardzo przydatne, gdy powłoki nie miały edycji wiersza poleceń, ale niektóre osoby nadal ich używają.

PS Ponieważ kodujesz dla bash:

echo $'#!/usr/bin/python\nimport string as s,random;print"".join(random.sample(s.letters+s.digits+s.punctuation,9))'>pg;chmod +x pg;./pg

Działa to na większości jednorożców:

echo python -c \''import string as s,random;print"".join(random.sample(s.letters+s.digits+s.punctuation,9))'\'>pg;chmod +x pg;./pg

(Nie to, że rozumiem, dlaczego chcesz utworzyć skrypt lub dlaczego nazwa skryptu musi składać się z dwóch liter).

Gilles „SO- przestań być zły”
źródło
Nie wiedziałem o tym $''. :) PS: Miało to zużyć te zapasowe postacie. Mam poczucie marnotrawstwa, gdy publikuję tweety krótsze niż 140 znaków.
badp
@badp: Więc spróbuj wygenerować niezapomniane hasła. (Jak w pwgenvs pwgen -s..)
Gilles „SO - przestań być zły”
Równie dobrze można użyć dadadodo do zapamiętania, ale bezsensownych haseł :)
badp
1

Powinienem był googlować, zanim zapytałem.

Ponieważ nie jesteś zależny od bash do rozwijania zmiennych [...], możesz zamiast tego użyć pojedynczych cudzysłowów. Ciągi w pojedynczych cudzysłowach nie są rozwijane przez bash.

honk w odpowiedzi na pytanie: Jak uniknąć wykrzyknika?

badp
źródło
1
Nie zaznaczam jednak tej odpowiedzi jako zaakceptowanej, ponieważ odpowiada ona tylko na ten konkretny przypadek. Zasadniczo nie można uciec bez rozszerzenia.
badp