การประเมินสตริงในเชลล์สคริปต์


8

ฉันทำตามคำแนะนำสคริปต์เปลือก bash นี้:

ในส่วนการเปรียบเทียบตัวเลขมันอ้างอิงตัวอย่าง:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

สิ่งที่ดูเหมือนจะเกิดขึ้นข้างต้นคือเราเก็บสตริงคำสั่งไว้ในตัวแปร bash จากนั้นเราเรียกใช้ echo บนตัวแปร สิ่งที่น่าจะเกิดขึ้นคือสตริงถูกประเมินและคำสั่ง wc ถูกดำเนินการและส่งคืนจำนวนบรรทัดไปยังเทอร์มินัลการควบคุม

ตกลงดังนั้นฉันจึงเปิดตัวเทอร์มินัลของฉันใน Ubuntu 12.04 และลองทำสิ่งที่คล้ายกัน:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

รอสักครู่ที่ไม่ได้ประเมินสตริงและส่งคืนจำนวนบรรทัด นั่นเพิ่งสะท้อนสตริงกลับไปที่เทอร์มินัล เหตุใดฉันจึงได้ผลลัพธ์ที่แตกต่าง


โปรดทราบว่า NUM ไม่เคยได้รับมอบหมายสตริงwc -l work.txtแทนจะกำหนดจำนวน 201
IGNIS

ทรัพยากรที่เกี่ยวข้อง: 3.5.4 คำสั่งชดเชยในคู่มืออ้างอิงทุบตี
Eliah Kagan

คำตอบ:


2

คุณต้องใช้ backticks เพื่อประเมินผลการแสดงออก

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

หากคุณต้องการเห็นเฉพาะ "1" ในเอาต์พุตให้ใช้คำสั่ง

$ num=`cat sample.txt | wc -l`
$ echo $num
1

และยังใช้งานได้:

$ num=`wc -l < sample.txt`
$ echo $num
1

สำหรับข้อมูลเพิ่มเติมดูความแตกต่างระหว่าง doublequotes "", singlequotes '' และ backticks ´´ บน commandline?


ความคิดใดที่ทำให้ฉันได้รับ '1 sample.txt' และไม่ใช่แค่ '1'
JohnMerlino

นั่นคือวิธีการwcทำงานของคำสั่ง ลองcat sample.txt | wc -lดู
Danatela

wc -l แสดงจำนวนบรรทัดที่มีอยู่ในไฟล์พร้อมกับชื่อไฟล์
Avinash Raj

5

โปรดทราบว่าสัญลักษณ์:

'

อ้างเดี่ยว

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

และ

`

backquote

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

ดังนั้น Backquote จะส่งคืนผลลัพธ์ของคำสั่งไปยังเอาต์พุตมาตรฐาน นั่นคือเหตุผล

`wc -l sample.txt`

ส่งคืนผลลัพธ์ของคำสั่งขณะที่

'wc -l sample.txt'

เพียงแค่กลับ "wc -l sample.txt" เป็นสตริงปกติ

ลองทำสิ่งนี้เป็นตัวอย่าง:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

และตอนนี้สะท้อนทั้งสามตัวแปร:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts

4

หากคุณต้องการดักจับเอาต์พุตของคำสั่งในตัวแปรคุณต้องใช้ backticks ``หรือล้อมรอบคำสั่งใน$():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

โปรดทราบว่าสตริงจะถูกประเมินจริงในขณะที่การประกาศตัวแปรไม่ใช่เมื่อคุณสะท้อน คำสั่งนั้นจะทำงานภายใน$()หรือย้อนกลับและผลลัพธ์ของคำสั่งนั้นจะถูกบันทึกเป็นค่าของตัวแปร

โดยทั่วไปคุณควรใช้$()แทน backticks ที่เลิกใช้แล้วและใช้เพื่อเหตุผลด้านความเข้ากันได้เท่านั้นและมีข้อ จำกัด มากกว่า ยกตัวอย่างเช่นคุณไม่สามารถสั่งคำสั่งซ้อนภายใน backticks ได้ แต่คุณสามารถ$():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

ดูกระทู้นี้ใน U&L สำหรับรายละเอียดเพิ่มเติมว่าทำไม``ควรหลีกเลี่ยง


1
ผมเห็นด้วยสคริปต์จะชอบที่จะ$( ) ` `แต่ดังที่คนพูดพล่าม backquotes ทำรัง echo $(date -d $(echo yesterday))กลายเป็นecho `date -d \`echo yesterday\``; จะกลายเป็นecho $(echo $(date -d $(echo yesterday))) echo `echo \`date -d \\\`echo yesterday\\\`\``ฉันพูดแบบนี้ไม่ใช่การโต้แย้งของคุณแต่เพื่อเสริมความแข็งแกร่ง : การหลบหนี backquotes ภายในทำให้` `ไวยากรณ์มีประสิทธิภาพมากกว่าที่ยอมรับบ่อย แต่การดูแลเป็นพิเศษ\แปลกประหลาดและยากที่จะให้เหตุผล ด้วย$( )สิ่งที่คุณเห็นมักจะเป็นสิ่งที่คุณได้รับ
Eliah Kagan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.