Chcę wydrukować kod do pliku za pomocą cat <<EOF >>
:
cat <<EOF >> brightup.sh
!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
curr=$((curr+406));
echo $curr > /sys/class/backlight/intel_backlight/brightness;
fi
EOF
ale kiedy sprawdzam dane wyjściowe pliku, otrzymuję to:
!/bin/bash
curr=1634
if [ -lt 4477 ]; then
curr=406;
echo > /sys/class/backlight/intel_backlight/brightness;
fi
Próbowałem umieszczać pojedyncze cudzysłowy, ale wynik zawiera również pojedyncze cudzysłowy. Jak mogę uniknąć tego problemu?
#!/bin/bash
i nic więcej -#!
to właśnie sprawia, że jest to poprawna linia shebang, a to, co następuje po niej, to ścieżka do tłumacza.man bash
i wyszukajHere Documents
. Wszystkie szczegóły.$(command)
zamiast`command`
. Aby uzyskać zawartość pliku, Bash ma$(<file)
Odpowiedzi:
Potrzebujesz tylko minimalnej zmiany; Cudzysłów separator dokumentu znajdującego się tutaj po
<<
.cat <<'EOF' >> brightup.sh
lub równoważnie z ukośnikiem odwrotnym:
Bez cytowania, dokument w tym miejscu zostanie zastąpiony zmiennymi, znaki odwrotne zostaną ocenione itd., Tak jak odkryłeś.
Jeśli potrzebujesz poszerzyć niektóre wartości, ale nie wszystkie, musisz indywidualnie uciec od tych, którym chcesz zapobiec.
cat <<EOF >>brightup.sh #!/bin/sh # Created on $(date # : <<-- this will be evaluated before cat;) echo "\$HOME will not be evaluated because it is backslash-escaped" EOF
będzie produkować
#!/bin/sh # Created on Fri Feb 16 11:00:18 UTC 2018 echo "$HOME will not be evaluated because it is backslash-escaped"
Zgodnie z sugestią @fedorqui , oto odpowiednia sekcja z
man bash
:źródło
Lub, używając swoich znaczników EOF, musisz zacytować początkowy znacznik, aby ekspansja nie została wykonana:
#-----v---v------ cat <<'EOF' >> brightup.sh #!/bin/bash curr=`cat /sys/class/backlight/intel_backlight/actual_brightness` if [ $curr -lt 4477 ]; then curr=$((curr+406)); echo $curr > /sys/class/backlight/intel_backlight/brightness; fi EOF
IHTH
źródło
To powinno działać, właśnie przetestowałem to i działało zgodnie z oczekiwaniami: nie miało miejsca żadne rozszerzenie, zamiana ani to, co masz.
cat <<< ' #!/bin/bash curr=`cat /sys/class/backlight/intel_backlight/actual_brightness` if [ $curr -lt 4477 ]; then curr=$((curr+406)); echo $curr > /sys/class/backlight/intel_backlight/brightness; fi' > file # use overwrite mode so that you don't keep on appending the same script to that file over and over again, unless that's what you want.
Korzystanie z poniższych również działa.
cat <<< ' > file ... code ...'
Warto również zauważyć, że podczas korzystania z heredoców ma miejsce, takie jak
<< EOF
podstawianie i rozwijanie zmiennych i tym podobne. Robiąc coś takiego:cat << EOF > file cd "$HOME" echo "$PWD" # echo the current path EOF
zawsze spowoduje rozszerzenie zmiennych
$HOME
i$PWD
. Więc jeśli twój katalog domowy to,/home/foobar
a obecna ścieżka to/home/foobar/bin
,file
będzie wyglądać następująco:cd "/home/foobar" echo "/home/foobar/bin"
zamiast oczekiwanego:
cd "$HOME" echo "$PWD"
źródło
<<<
są dostępne tylko począwszy od Bash 3 i nie można ich przenosić na inne powłoki.<<<
jest również dostępny w ZshWiem, że to pytanie sprzed dwóch lat, ale jest to szybka odpowiedź dla tych, którzy szukają „jak to zrobić”.
Jeśli nie chcesz umieszczać niczego w cudzysłowie, możesz po prostu napisać blok tekstu do pliku i zmienić zmienne, które chcesz wyeksportować jako tekst (na przykład do użycia w skrypcie) i nie uciec przed tymi, które chcesz eksportuj jako wartość zmiennej.
#!/bin/bash FILE_NAME="test.txt" VAR_EXAMPLE="\"string\"" cat > ${FILE_NAME} << EOF \${VAR_EXAMPLE}=${VAR_EXAMPLE} in ${FILE_NAME} EOF
Zapisuje "$ {VAR_EXAMPLE} =" string "w test.txt" do test.txt
Można to również użyć do wyprowadzenia bloków tekstu do konsoli z tymi samymi regułami, pomijając nazwę pliku
#!/bin/bash VAR_EXAMPLE="\"string\"" cat << EOF \${VAR_EXAMPLE}=${VAR_EXAMPLE} to console EOF
Wyświetla "$ {VAR_EXAMPLE} =" ciąg "do konsoli" do konsoli
źródło