Here Document (Heredoc) เป็น Input หรือ File Stream Literal ที่ถือว่าเป็น Special Block ของโค้ด Block นี้จะถูกส่งให้ Command ประมวลผล Heredoc มาจาก UNIX Shells พบได้ใน Linux Shells ยอดนิยมอย่าง sh, tcsh, ksh, bash, zsh, csh ภาษาโปรแกรมอื่นๆ เช่น Perl, Ruby, PHP ก็รองรับ Heredoc
โครงสร้างของ Heredoc
Heredoc ใช้ Angle Brackets 2 ตัว (<<) ตามด้วย Delimiter Token Delimiter Token เดียวกันจะใช้จบ Block โค้ด ทุกอย่างภายใน Delimiter ถือว่าเป็น Block ของโค้ด
ดูตัวอย่างด้านล่าง Redirect Block ไป Cat Command Delimiter ตั้งเป็น BLOCK จบด้วย BLOCK เดียวกัน
cat << BLOCK
Hello world
Today date is $(date +%F)
My home directory = ${HOME}
BLOCK
NOTE: ควรใช้ Delimiter Token เดียวกันเริ่ม Block และจบ Block
สร้าง Multiline Comments
ถ้าเขียน Bash บ้าง คุณรู้ว่า Bash โดย Default ไม่รองรับ Multiline Comments เหมือน C หรือ Java ใช้ HereDoc แก้ได้
นี่ไม่ใช่ Built-in Feature ของ Bash รองรับ Multi-line Comment แค่ Hack ถ้าไม่ Redirect Heredoc ไป Command ใด Interpreter จะอ่าน Block แค่นั้นและไม่ Execute อะไร
<< COMMENT This is comment line 1 This is comment line 2 This is comment line 3 COMMENT
จัดการ White Spaces
โดย Default Heredoc ไม่ Suppress White Space Characters (Tabs, Spaces) Override ได้ด้วยการเพิ่ม Dash (-) หลัง (<<) ตามด้วย Delimiter จะ Suppress Tab Spaces ทั้งหมด แต่ White Spaces จะไม่ Suppress
cat <<- BLOCK This line has no whitespace. This line has 2 white spaces at the beginning. This line has a single tab. This line has 2 tabs. This line has 3 tabs. BLOCK
Variable และ Command Substitution
Heredoc รองรับ Variable Substitution Variables เป็น User-defined หรือ Environmental Variables
TODAY=$(date +%F)
cat << BLOCK1
# User defined variables
Today date is = ${TODAY}
# Environ Variables
I am running as = ${USER}
My home dir is = ${HOME}
I am using ${SHELL} as my shell
BLOCK1
เช่นกัน รัน Commands ใดๆ ภายใน Heredoc Code Block ได้
cat << BLOCK2 $(uname -a) BLOCK2
Escaping Special Characters
มีหลายวิธี Escape Special Characters ทั้ง Character Level และ Doc Level
Escape ตัวละตัว ใช้ Backslash (\)
cat << BLOCK4
\$(uname -a)
BLOCK4
cat << BLOCK5
Today date is = \${TODAY}
BLOCK5
Escape ทุก Special Characters ใน Block ใส่ Delimiter ใน Single Quotes, Double Quotes หรือ Prefix Delimiter ด้วย Backslash
cat << 'BLOCK1'
I am running as = ${USER}
BLOCK1
cat << "BLOCK2"
I am running as = ${USER}
BLOCK2
cat << \BLOCK3
I am running as = ${USER}
BLOCK3
ตอนนี้เรารู้โครงสร้าง Heredoc และการทำงาน มาดูตัวอย่างเพิ่ม 2 พื้นที่ทั่วไปที่ใช้ Heredoc คือ รัน Block ของ Commands ผ่าน SSH และส่ง SQL Queries ผ่าน Heredoc
ตัวอย่างด้านล่าง พยายาม Execute Block ของโค้ดใน Remote Server ผ่าน SSH
ตัวอย่างด้านล่าง ส่ง Select Statement ไป psql เชื่อม Database รัน Query นี่เป็น Alternative Way รัน Query ใน psql ภายใน Bash Script แทน Flag -f รัน .sql File
#!/usr/bin/env bash
UNAME=postgres
DBNAME=testing
psql --username=${UNAME} --password --dbname=${DBNAME} << BLOCK
SELECT * FROM COUNTRIES WHERE region_id = 4;
BLOCK
ขอจบเท่านี้ มีอะไรทำได้กับ Heredoc มากกว่าที่แสดง หากมี Hack ที่มีประโยชน์ Post ใน Comment Section ให้ Readers ได้ประโยชน์