ฉันจะเขียนเอกสารที่นี่ไปยังไฟล์ใน Bash script ได้อย่างไร?
ฉันจะเขียนเอกสารที่นี่ไปยังไฟล์ใน Bash script ได้อย่างไร?
คำตอบ:
อ่านขั้นสูงทุบตี Scripting คู่มือบทที่ 19 ที่นี่เอกสาร
นี่คือตัวอย่างที่จะเขียนเนื้อหาไปยังไฟล์ที่ /tmp/yourfilehere
cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
This line is indented.
EOF
โปรดทราบว่า 'EOF' สุดท้าย (The LimitString
) ไม่ควรมีช่องว่างด้านหน้าคำเพราะหมายความว่าLimitString
จะไม่ได้รับการยอมรับ
ในเชลล์สคริปต์คุณอาจต้องการใช้การเยื้องเพื่อให้โค้ดอ่านได้อย่างไรก็ตามสิ่งนี้อาจมีผลที่ไม่พึงประสงค์จากการเยื้องข้อความภายในเอกสารที่นี่ของคุณ ในกรณีนี้ใช้<<-
(ตามด้วยเส้นประ) เพื่อปิดการใช้งานแท็บนำ ( โปรดทราบว่าเพื่อทดสอบสิ่งนี้คุณจะต้องแทนที่ช่องว่างนำหน้าด้วยอักขระแท็บเนื่องจากฉันไม่สามารถพิมพ์อักขระแท็บจริงได้ที่นี่)
#!/usr/bin/env bash
if true ; then
cat <<- EOF > /tmp/yourfilehere
The leading tab is ignored.
EOF
fi
หากคุณไม่ต้องการตีความตัวแปรในข้อความให้ใช้เครื่องหมายคำพูดเดี่ยว:
cat << 'EOF' > /tmp/yourfilehere
The variable $FOO will not be interpreted.
EOF
ในการไพพ์ heredoc ผ่านไพพ์ไลน์คำสั่ง:
cat <<'EOF' | sed 's/a/b/'
foo
bar
baz
EOF
เอาท์พุท:
foo
bbr
bbz
... หรือเพื่อเขียน heredoc ไปยังไฟล์โดยใช้sudo
:
cat <<'EOF' | sed 's/a/b/' | sudo tee /etc/config_file.conf
foo
bar
baz
EOF
<<<
สิ่งที่พวกเขาเรียกว่า?
<<<
ถูกเรียกว่า 'Here Strings' รหัสเหมือนจะส่งผลให้ในสตริงtr a-z A-Z <<< 'one two three'
ONE TWO THREE
ข้อมูลเพิ่มเติมที่en.wikipedia.org/wiki/Here_document#Here_strings
<<'EOF'
<<EOF
แทนที่จะใช้cat
และการเปลี่ยนเส้นทาง I / O อาจมีประโยชน์ในการใช้tee
แทน:
tee newfile <<EOF
line 1
line 2
line 3
EOF
มันกระชับกว่าและแตกต่างจากผู้ให้บริการเปลี่ยนเส้นทางซึ่งสามารถใช้ร่วมกับsudo
หากคุณต้องการเขียนไปยังไฟล์ที่มีสิทธิ์รูท
> /dev/null
ที่ท้ายบรรทัดแรกเพื่อป้องกันเนื้อหาของไฟล์ here ที่จะถูกแสดงเป็น stdout เมื่อไฟล์ถูกสร้างขึ้น
sudo
มากกว่าเพราะความกะทัดรัด :-)
man tee
ตรวจสอบ ใช้การ-a
ตั้งค่าสถานะเพื่อผนวกแทนการเขียนทับ
บันทึก:
คำถาม (วิธีเขียนเอกสารที่นี่ (aka heredoc ) ไปยังไฟล์ในสคริปต์ทุบตี) มี (อย่างน้อย) 3 มิติหลักหรือคำถามย่อยอิสระ:
root
) เป็นเจ้าของไฟล์หรือไม่(มีส่วนข้อมูลย่อย / คำถามย่อยอื่น ๆ ที่ฉันไม่ถือว่าสำคัญพิจารณาแก้ไขคำตอบนี้เพื่อเพิ่ม!) ต่อไปนี้เป็นชุดค่าผสมที่สำคัญยิ่งขึ้นของมิติของคำถามข้างต้นพร้อมตัวระบุที่แตกต่างหลากหลาย - ไม่มีอะไรเลย ศักดิ์สิทธิ์EOF
เพียงตรวจสอบให้แน่ใจว่าสตริงที่คุณใช้เป็นตัวระบุการคั่นของคุณจะไม่เกิดขึ้นภายใน heredoc ของคุณ:
ในการเขียนทับไฟล์ที่มีอยู่ (หรือเขียนไปยังไฟล์ใหม่) ที่คุณเป็นเจ้าของให้แทนที่การอ้างอิงตัวแปรภายใน heredoc:
cat << EOF > /path/to/your/file
This line will write to the file.
${THIS} will also write to the file, with the variable contents substituted.
EOF
ในการต่อท้ายไฟล์ที่มีอยู่ (หรือเขียนลงในไฟล์ใหม่) ที่คุณเป็นเจ้าของให้แทนที่การอ้างอิงตัวแปรภายใน heredoc:
cat << FOE >> /path/to/your/file
This line will write to the file.
${THIS} will also write to the file, with the variable contents substituted.
FOE
หากต้องการเขียนทับไฟล์ที่มีอยู่ (หรือเขียนไปยังไฟล์ใหม่) ที่คุณเป็นเจ้าของด้วยเนื้อหาที่แท้จริงของ heredoc:
cat << 'END_OF_FILE' > /path/to/your/file
This line will write to the file.
${THIS} will also write to the file, without the variable contents substituted.
END_OF_FILE
ในการต่อท้ายไฟล์ที่มีอยู่ (หรือเขียนลงในไฟล์ใหม่) ที่คุณเป็นเจ้าของด้วยเนื้อหาที่แท้จริงของ heredoc:
cat << 'eof' >> /path/to/your/file
This line will write to the file.
${THIS} will also write to the file, without the variable contents substituted.
eof
ในการเขียนทับไฟล์ที่มีอยู่ (หรือเขียนไปยังไฟล์ใหม่) ที่เป็นของ root ให้แทนที่การอ้างอิงตัวแปรภายใน heredoc:
cat << until_it_ends | sudo tee /path/to/your/file
This line will write to the file.
${THIS} will also write to the file, with the variable contents substituted.
until_it_ends
ในการต่อท้ายไฟล์ที่มีอยู่ (หรือเขียนลงในไฟล์ใหม่) user = foo ที่เป็นเจ้าของโดยมีเนื้อหาตามตัวอักษรของ heredoc:
cat << 'Screw_you_Foo' | sudo -u foo tee -a /path/to/your/file
This line will write to the file.
${THIS} will also write to the file, without the variable contents substituted.
Screw_you_Foo
-a
== --append
; เช่น->tee -a
tee
ดูinfo tee
(ฉันจะพูดที่นี่ แต่ความเห็นมาร์กอัป จำกัด มากเกินไป
sudo tee /path/to/your/file << 'Screw_you_Foo'
หรือไม่?
FOE
แทนที่จะเป็นEOF
ในตัวอย่างผนวก?
เพื่อสร้างคำตอบของ @ Livven ต่อไปนี้เป็นชุดค่าผสมที่มีประโยชน์
การทดแทนตัวแปร, แท็บนำยังคงอยู่, เขียนทับไฟล์, echo to stdout
tee /path/to/file <<EOF
${variable}
EOF
ไม่มีการทดแทนตัวแปร , แท็บนำยังคงอยู่, เขียนทับไฟล์, echo to stdout
tee /path/to/file <<'EOF'
${variable}
EOF
การแทนที่ตัวแปร, แท็บนำออก , เขียนทับไฟล์, echo to stdout
tee /path/to/file <<-EOF
${variable}
EOF
การทดแทนตัวแปร, แท็บนำยังคงอยู่, ต่อท้ายไฟล์ , echo to stdout
tee -a /path/to/file <<EOF
${variable}
EOF
การทดแทนตัวแปร, แท็บนำยังคงอยู่, เขียนทับไฟล์, ไม่มี echo to stdout
tee /path/to/file <<EOF >/dev/null
${variable}
EOF
ด้านบนสามารถใช้ร่วมกับได้sudo
เช่นกัน
sudo -u USER tee /path/to/file <<EOF
${variable}
EOF
เมื่อจำเป็นต้องมีการอนุญาตรูทสำหรับไฟล์ปลายทางให้ใช้|sudo tee
แทน>
:
cat << 'EOF' |sudo tee /tmp/yourprotectedfilehere
The variable $FOO will *not* be interpreted.
EOF
สำหรับคนในอนาคตที่อาจมีปัญหานี้รูปแบบต่อไปนี้ใช้งานได้:
(cat <<- _EOF_
LogFile /var/log/clamd.log
LogTime yes
DatabaseDirectory /var/lib/clamav
LocalSocket /tmp/clamd.socket
TCPAddr 127.0.0.1
SelfCheck 1020
ScanPDF yes
_EOF_
) > /etc/clamd.conf
cat << END > afile
ตามด้วย heredoc ทำงานได้ดีอย่างสมบูรณ์
cat
ดังที่แสดงในคำตอบที่ยอมรับ
cat
ทำงานทั้งหมดภายใน subshell และผลลัพธ์ทั้งหมดของ subshell จะถูกเปลี่ยนเส้นทางไปยังไฟล์
ตัวอย่างเช่นคุณสามารถใช้มันได้:
ก่อน (ทำการเชื่อมต่อ ssh):
while read pass port user ip files directs; do
sshpass -p$pass scp -o 'StrictHostKeyChecking no' -P $port $files $user@$ip:$directs
done <<____HERE
PASS PORT USER IP FILES DIRECTS
. . . . . .
. . . . . .
. . . . . .
PASS PORT USER IP FILES DIRECTS
____HERE
ที่สอง (รันคำสั่ง):
while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
COMMAND 1
.
.
.
COMMAND n
ENDSSH1
done <<____HERE
PASS PORT USER IP
. . . .
. . . .
. . . .
PASS PORT USER IP
____HERE
ที่สาม (รันคำสั่ง):
Script=$'
#Your commands
'
while read pass port user ip; do
sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip "$Script"
done <<___HERE
PASS PORT USER IP
. . . .
. . . .
. . . .
PASS PORT USER IP
___HERE
มา (ใช้ตัวแปร):
while read pass port user ip fileoutput; do
sshpass -p$pass ssh -o 'StrictHostKeyChecking no' -p $port $user@$ip fileinput=$fileinput 'bash -s'<<ENDSSH1
#Your command > $fileinput
#Your command > $fileinput
ENDSSH1
done <<____HERE
PASS PORT USER IP FILE-OUTPUT
. . . . .
. . . . .
. . . . .
PASS PORT USER IP FILE-OUTPUT
____HERE
ฉันชอบวิธีนี้เพื่อความกระชับอ่านง่ายและนำเสนอในสคริปต์ที่เยื้อง:
<<-End_of_file >file
→ foo bar
End_of_file
ในกรณีที่→
เป็นtabตัวอักษร