<< EOF >> kod içeren bir dosya nasıl oluşturulur?


104

Şunu kullanarak bir dosyaya kod yazdırmak istiyorum 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

ancak dosya çıktısını kontrol ettiğimde şunu alıyorum:

!/bin/bash
curr=1634
if [  -lt 4477 ]; then
   curr=406;
   echo   > /sys/class/backlight/intel_backlight/brightness;
fi

Tek tırnak işareti koymayı denedim ama çıktıda tek tırnak işareti de var. Bu sorunu nasıl önleyebilirim?


2
Ayrıca shebang'ı da düzeltmelisiniz. İlk satırın kelimenin tam anlamıyla olması #!/bin/bashve başka bir şey olmaması gerekir - #!onu geçerli bir shebang satırına dönüştüren şeydir ve ondan sonra gelen, tercümana giden yoldur.
üçlü

1
bakın man bashve arayın Here Documents. Orada tüm detaylar.
Hong

1
Geç gelen bir yana, süreç ikamesi için modern sözdizimi $(command)yerine `command`. Bir dosyanın içeriğini elde etmek için, Bash vardır$(<file)
tripleee

Yanıtlar:


165

Yalnızca minimum bir değişikliğe ihtiyacınız var; buradaki belge sınırlayıcısını tek tırnak içine alın <<.

cat <<'EOF' >> brightup.sh

veya eşdeğer olarak ters eğik çizgiden kaçının:

cat <<\EOF >>brightup.sh

Alıntı yapmadan, buradaki belge değişken ikameye uğrayacak, ters işaretler değerlendirilecek, vb. Sizin keşfettiğiniz gibi.

Değerlerin tümünü olmasa da bazılarını genişletmeniz gerekiyorsa, önlemek istediklerinizden ayrı ayrı kaçmanız gerekir.

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

üretecek

#!/bin/sh
# Created on Fri Feb 16 11:00:18 UTC 2018
echo "$HOME will not be evaluated because it is backslash-escaped"

@Fedorqui tarafından önerildiği gibi , şuradaki ilgili bölüm man bash:

İşte Belgeler

Bu tür yeniden yönlendirme, kabuğa, yalnızca sınırlayıcı içeren (sonda boşluklar olmadan) bir satır görünene kadar mevcut kaynaktan gelen girişi okumasını söyler. O noktaya kadar okunan tüm satırlar daha sonra bir komut için standart girdi olarak kullanılır.

Buradaki belgelerin biçimi şöyledir:

      <<[-]word
              here-document
      delimiter

Word üzerinde hiçbir parametre genişletmesi, komut ikamesi, aritmetik genişletme veya yol adı genişletmesi gerçekleştirilmez. Sözcükteki herhangi bir karakter tırnak içine alınmışsa, sınırlayıcı sözcük üzerindeki alıntı kaldırmanın sonucudur ve buradaki-belgedeki satırlar genişletilmez. Sözcük tırnaksız ise, buradaki belgenin tüm satırları parametre yorumlamasına, komut ikamesine ve aritmetik genişletmeye tabidir . İkinci durumda, \ karakter dizisi göz ardı edilir ve \, $ ve `karakterlerini alıntılamak için \ kullanılmalıdır.


1
Ben işaretlediğiniz bkz değişkenleri genişleyen yorumlu metin nasıl önlenir? bunun bir kopyası olarak. İtiraz yok, sadece benimkinde yaptığım gibi Bash dokümanları referansını dahil edeceğim (ki bu sadece 13 bin ziyaretin neredeyse 100 tekrarı var, bu yüzden oldukça faydalı görünüyor).
fedorqui 'ÖYLESİNE zarar vermeyi bırak'

@fedorqui Belki de bu soruya verdiğiniz cevabı aslında aktarmak istersiniz? Veya yinelenen işaretlemeyi tam tersi şekilde değiştirebiliriz; Sadece soru puanına baktım, cevap puanlarına çok değil.
üçlü

Mmm onları birleştirmeye ne dersiniz , bunu hedef soru olarak almak? Yinelenen sorunun iyi bir başlığı var, sadece çok uzun. Ancak, bir şekilde son zamanlarda oldukça fazla ilgi gördü ( her ay bazı olumlu oylar alıyorum ).
fedorqui,

@fedorqui Birleşme kavramını seviyorum ama pratikte hiç görmedim; Durumu doğru anlarsam, modlar basit olmayan birleştirmeleri kaldıramaz çünkü zorluklar ve karmaşıklıklar faydalardan çok daha ağır basar. Bir veya iki kez yaptığım şey, faydalı ve yükseltilmiş bir cevabı silmek ve farklı bir soru altında yeniden yayınlamak, ancak bu geçici çözümü pek tavsiye edemem.
üçlü

Ne zaman yapmaya değeceğini söylemek zor. Daha önce iyi bir soru olduğunu fark etmeden iyi bir soru gönderildiğinde modladığım bir sitede yaptım, her ikisi de iyi cevaplara sahip. 90+ puanlı cevabımı kaldırmak o soruyu yetim bırakacağı için iyi bir plan gibi görünmüyor.
fedorqui 'O zaman zarar vermeyi bırakın'

20

Veya, EOF işaretlerinizi kullanarak, genişletme yapılmaması için ilk işaretleyiciyi alıntı yapmanız gerekir:

#-----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


1
Gönderinizi düzenlerdim, ancak güvenli olmak için #! / Bin / bash ve! / Bin / bash olmamalı mı?
Matthew Hoggan

@MatthewHoggan: Evet, haklısın! Yakaladığınız için teşekkürler. Şimdi tamir ediyorum.
shellter

16

Bu işe yaramalı, sadece test ettim ve beklendiği gibi çalıştı: genişleme, ikame veya sahip olduğunuz şey olmadı.

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. 

Aşağıdakileri kullanmak da işe yarar.

cat <<< ' > file
 ... code ...'

Ayrıca, << EOFikame ve değişken genişletme gibi yorumlu metinleri kullanırken ve benzerlerinin gerçekleştiğini belirtmek gerekir . Öyleyse böyle bir şey yapmak:

cat << EOF > file
cd "$HOME"
echo "$PWD" # echo the current path
EOF

her zaman değişkenlerin genişlemesi ile sonuçlanır $HOMEve $PWD. Ana dizininiz Yani eğer /home/foobarve geçerli yoldur /home/foobar/bin, filebu gibi görünecektir:

cd "/home/foobar"
echo "/home/foobar/bin"

beklenen yerine:

cd "$HOME"
echo "$PWD"

2
Tek tırnak içindeki bir buradaki dizge açıkça tek tırnak içeremez, bu da engelleyici bir konu olabilir. Hem tek hem de çift tırnak içermesi gereken bir betiğiniz varsa, burada belgeler tek mantıklı çözümdür, ancak bu elbette OP'nin basit örneğinde durum böyle değildir. Ayrıca, teğet olarak, buradaki dizeler <<<yalnızca Bash 3'ten başlayarak kullanılabilir ve diğer mermilere taşınabilir değildir.
üçlü

<<<Zsh
Alexej

3
bugün, dosya adının, heredocun açılışını hemen takip etmesini sağlayabileceğinizi öğrendim. Teşekkürler @AlexejMagura!
chaseadamsio

0

Bunun iki yıllık bir soru olduğunu biliyorum, ancak bu bir 'nasıl yapılır' arayanlar için hızlı bir cevap.

Herhangi bir şeyin etrafına tırnak işareti koymak zorunda kalmak istemiyorsanız, basitçe bir dosyaya bir metin bloğu yazabilir ve metin olarak dışa aktarmak istediğiniz değişkenlerden kaçınabilirsiniz (örneğin bir komut dosyasında kullanmak için) ve istediğiniz birinin dışına çıkmayabilirsiniz. değişkenin değeri olarak dışa aktar.

#!/bin/bash

FILE_NAME="test.txt"
VAR_EXAMPLE="\"string\""

cat > ${FILE_NAME} << EOF
\${VAR_EXAMPLE}=${VAR_EXAMPLE} in ${FILE_NAME}  
EOF

Test.txt dosyasına "$ {VAR_EXAMPLE} =" string "yazacak

Bu, dosya adını atlayarak aynı kurallara sahip metin bloklarını konsola çıkarmak için de kullanılabilir.

#!/bin/bash

VAR_EXAMPLE="\"string\""

cat << EOF
\${VAR_EXAMPLE}=${VAR_EXAMPLE} to console 
EOF

Konsola "$ {VAR_EXAMPLE} =" dizge "çıktılar

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.