ความแตกต่างระหว่างgrep apple fileและgrep "apple" fileคืออะไร? การใส่เครื่องหมายคำพูดทำอะไร? ทั้งคู่ดูเหมือนจะทำงานและทำสิ่งเดียวกัน (แสดงบรรทัดเดียวกัน)
ความแตกต่างระหว่างgrep apple fileและgrep "apple" fileคืออะไร? การใส่เครื่องหมายคำพูดทำอะไร? ทั้งคู่ดูเหมือนจะทำงานและทำสิ่งเดียวกัน (แสดงบรรทัดเดียวกัน)
คำตอบ:
เครื่องหมายอัญประกาศมีผลต่ออักขระที่เชลล์ของคุณพิจารณาเป็นพิเศษและมีความหมายทางไวยากรณ์ ในตัวอย่างของคุณสิ่งนี้ไม่ได้สร้างความแตกต่างเพราะappleไม่มีอักขระดังกล่าว
แต่พิจารณาอีกตัวอย่างหนึ่ง: grep apple tree fileจะค้นหาคำappleในไฟล์treeและfileในขณะที่grep "apple tree" fileจะค้นหาคำในไฟล์apple tree fileเครื่องหมายคำพูดบอกว่าทุบตีว่าคำในพื้นที่"apple tree"ไม่ได้เริ่มพารามิเตอร์ใหม่ แต่จะต้องเป็นส่วนหนึ่งของพารามิเตอร์ปัจจุบัน grep apple\ tree fileจะให้ผลลัพธ์ที่เหมือนกันเพราะ\บอกให้ทุบตีเพื่อเพิกเฉยต่อความหมายพิเศษของตัวละครต่อไปนี้และปฏิบัติต่อมันอย่างแท้จริง
") และคำพูดเดียว ( ') อัญประกาศเดี่ยวป้องกันการตีความของอักขระบางตัวเช่นใน$ขณะที่เครื่องหมายคำพูดคู่อนุญาตการตีความ เช่นgrep '${USER}'จะค้นหาข้อความ${USER}ในขณะที่grep "${USER}"จะค้นหาข้อความที่ตัวแปรUSERมี (เช่นjohnstacen)
อัญประกาศคู่อนุญาตให้มีการประเมินราคาอัญประกาศเดี่ยวป้องกันการประเมินผลไม่มีเครื่องหมายอัญประกาศอนุญาตให้มีการขยายสัญลักษณ์แทนเมื่อใช้บนบรรทัดคำสั่ง ในฐานะที่เป็นตัวอย่างที่วางแผนไว้:
[user@work test]$ ls .
A.txt B.txt C.txt D.cpp
# The following is the same as writing echo 'A.txt B.txt C.txt D.cpp'
[user@work test]$ echo *
A.txt B.txt C.txt D.cpp
[user@work test]$ echo "*"
*
[user@work test]$ echo '*'
*
# The following is the same as writing echo 'A.txt B.txt C.txt'
[user@work test]$ echo *.txt
A.txt B.txt C.txt
[user@work test]$ echo "*.txt"
*.txt
[user@work test]$ echo '*.txt'
*.txt
[user@work test]$ myname=is Fred; echo $myname
bash: Fred: command not found
[user@work test]$ myname=is\ Fred; echo $myname
is Fred
[user@work test]$ myname="is Fred"; echo $myname
is Fred
[user@work test]$ myname='is Fred'; echo $myname
is Fred
การทำความเข้าใจวิธีการทำงานของคำพูดเป็นหัวใจสำคัญในการทำความเข้าใจ Bash ตัวอย่างเช่น:
# for will operate on each file name separately (like an array), looping 3 times.
[user@work test]$ for f in $(echo *txt); do echo "$f"; done;
A.txt
B.txt
C.txt
# for will see only the string, 'A.txt B.txt C.txt' and loop just once.
[user@work test]$ for f in "$(echo *txt)"; do echo "$f"; done;
A.txt B.txt C.txt
# this just returns the string - it can't be evaluated in single quotes.
[user@work test]$ for f in '$(echo *txt)'; do echo "$f"; done;
$(echo *txt)
คุณสามารถใช้อัญประกาศเดี่ยวเพื่อส่งคำสั่งผ่านตัวแปร เครื่องหมายคำพูดเดี่ยวจะป้องกันการประเมินผล เครื่องหมายคำพูดคู่จะประเมิน
# This returns three distinct elements, like an array.
[user@work test]$ echo='echo *.txt'; echo $($echo)
A.txt B.txt C.txt
# This returns what looks like three elements, but it is actually a single string.
[user@work test]$ echo='echo *.txt'; echo "$($echo)"
A.txt B.txt C.txt
# This cannot be evaluated, so it returns whatever is between quotes, literally.
[user@work test]$ echo='echo *.txt'; echo '$($echo)'
$($echo)
คุณสามารถใช้เครื่องหมายคำพูดเดี่ยวภายในเครื่องหมายคำพูดคู่และคุณสามารถใช้เครื่องหมายคำพูดคู่ภายในเครื่องหมายคำพูดคู่ แต่เครื่องหมายอัญประกาศคู่ภายในเครื่องหมายคำพูดเดี่ยวไม่ควรทำ (โดยไม่ต้องหลบหนีพวกเขา)จะไม่ถูกประเมิน ไม่ควรทำเครื่องหมายคำพูดเดี่ยวในเครื่องหมายคำพูดเดี่ยว (โดยไม่ต้องหลีกหนี)
คุณจะต้องเข้าใจราคาอย่างถี่ถ้วนเพื่อใช้ Bash อย่างมีประสิทธิภาพ สำคัญมาก!
ตามกฎทั่วไปฉันไม่ใช้เครื่องหมายอัญประกาศถ้าฉันต้องการให้ Bash ขยายบางสิ่งออกเป็นองค์ประกอบ (เช่นอาร์เรย์) ฉันใช้เครื่องหมายอัญประกาศเดี่ยวสำหรับสตริงตัวอักษรที่ไม่ได้รับการแก้ไข ที่น่าจะส่งคืนสตริงประเภทใดก็ได้ นี่คือเพื่อให้แน่ใจว่าช่องว่างและอักขระพิเศษจะถูกเก็บไว้
grep a*b equations.txtแล้วมันจะค้นหาa*bเว้นแต่จะมีไฟล์ในไดเรกทอรีปัจจุบันเริ่มต้นด้วย, และลงท้ายด้วย b ในกรณีนี้ (เพราะ (ba) sh จะขยายชื่อไฟล์ในบรรทัดคำสั่ง) grep จะถูกเรียกด้วย พารามิเตอร์ที่แตกต่างกันอย่างสมบูรณ์ทำให้ได้ผลลัพธ์ที่ต่างกัน นี่เป็นปัญหาที่พบได้บ่อยกว่าเนื่องจากคำสั่งเช่นfind . -name *.txtนั้นจะส่งผลให้เกิดพฤติกรรมที่ไม่คาดคิดหากมีไฟล์ txt ในไดเรกทอรีปัจจุบัน มันจะดีกว่าที่จะใช้คำพูดในกรณีนี้