ไม่สามารถใช้! $ in script?


11

เพียงแค่สงสัยว่าทำไมสิ่งนี้ถึงไม่ทำงาน

#!/bin/bash 

ls /bin
ls !$

ฉันคาดว่าจะทำงานls /binสองครั้ง แต่ข้อผิดพลาดที่สองทำให้เกิดข้อผิดพลาดตามที่!$ไม่ถูกตีความ

ฉันพลาดอะไรบางอย่างหรือ!$ทำงานเฉพาะในบรรทัดคำสั่งเท่านั้น

ฉันไม่พบส่วนที่เกี่ยวข้องในman bash(บน mac)


9
แม้ว่าจะมีวิธีแก้ปัญหานี้เป็นวิธีที่ดีที่สุดในการบรรลุเป้าหมายในสคริปต์หรือไม่ ประวัติถูกปิดการใช้งานโดยค่าเริ่มต้นด้วยเหตุผลเมื่อคุณเรียกใช้ไม่โต้ตอบ - สคริปต์ยาวจะส่งสแปมไฟล์. bash_history ไม่ได้บอกว่ามันไม่คุ้มค่าที่จะถาม แต่ถ้าคุณคิดที่จะใช้สิ่งนี้ในสคริปต์นี่เป็นวิธีที่ดีที่สุดจริง ๆ หรือ?
flungo

คำตอบ:


26

ประวัติความเป็นมาและการขยายตัวของประวัติศาสตร์จะถูกยกเลิกโดยปริยายเมื่อเปลือกทำงานไม่โต้ตอบ

คุณต้องการ:

#!/bin/bash 

set -o history
set -o histexpand

ls /bin
ls !$

หรือ:

SHELLOPTS=history:histexpand bash script.sh

มันจะส่งผลกระทบต่ออินสแตนซ์ทุบตีทั้งหมดที่script.shอาจทำงานได้


9
ระมัดระวังกับ SHELLOPTS มันจะส่งผลกระทบต่อการbashทำงานscript.shนั้น แต่ยังรวมถึงbashกรณีอื่น ๆ ทั้งหมดที่script.shในที่สุดอาจทำงาน (เช่นbashสคริปต์อื่น ๆ... )
Stéphane Chazelas

และจะไม่ส่งผลกระทบต่ออินสแตนซ์อื่น ๆ bashที่เรียกใช้สคริปต์ของคุณ
แบล็กไลท์ส่องแสง

ฉันคิดว่าคำตอบนี้จะดีขึ้นหากความคิดเห็นของ @ StéphaneChazelasถูกแก้ไข
Oliphaunt - คืนสถานะโมนิก้า

7

สิ่งที่มีสติที่ต้องทำก็คือ

ls /bin
ls $_

หรือ

set ls /bin
$*
$*

หรือ

c='ls /bin'
$c
$c

Caveats: มันควรค่าแก่การจดจำว่าสิ่งเหล่านี้มาพร้อมกับข้อผิดพลาดบางอย่าง ราคา $ _ ทางออกเดียวที่จับอาร์กิวเมนต์เดียวครั้งสุดท้ายเมื่อ: เพื่อls foo barจะออกจาก $ _ barมีเพียง หนึ่งใช้setจะแทนที่การขัดแย้ง ( $1, $2ฯลฯ ) และสิ่งเหล่านี้ตามที่เขียนจะใช้ได้ แต่เมื่อวางนัยกับคำสั่งที่ซับซ้อนมากขึ้น (ในกรณีที่การหลบหนีและพื้นที่ว่าง) คุณอาจพบปัญหาบางอย่าง ตัวอย่างเช่น: ls 'foo bar'(โดยที่อาร์กิวเมนต์ชื่อพา ธ เดียวfoo barมีช่องว่างสองช่องขึ้นไปหรืออักขระช่องว่างอื่น ๆ ) จะไม่ทำงานอย่างถูกต้องในตัวอย่างเหล่านี้ การหลบหนีที่เหมาะสม (อาจรวมกับevalคำสั่ง) หรืออาจใช้"$@"แทน$*อาจจำเป็นต้องหลีกเลี่ยงกรณีเหล่านี้


1
+1 สำหรับคำตอบที่พกพาได้และไม่ละเมิดความเป็น bashism ที่ตั้งใจจะทำให้การใช้งานแบบโต้ตอบง่ายขึ้น (เช่นกันปรารถนาทุบตีเพื่อโต้ตอบขยายเครื่องหมายอัศเจรีย์ในการตั้งค่าเริ่มต้นคือสิ่งที่ฉันพบ counterintuitive เป็นผู้ใช้ของเปลือกหอยอื่น ๆ และต่อต้านเพราะมันเสมอสกรูฉันเมื่อฉันพยายามที่จะทำคำสั่งเชลล์บางซับซ้อน)
mtraceur

แม้ว่าที่เขียนไว้ในขณะนี้ฉันลังเลที่จะให้ +1 เนื่องจากปัญหาเชลล์สคริปเตอร์มือใหม่น่าจะมีเมื่อพยายามที่จะพูดคุยกับคำสั่งที่ซับซ้อนมากขึ้น ฉันแนะนำให้แก้ไขอย่างน้อยก็เพิ่มย่อหน้า caveat เพื่ออธิบายข้อผิดพลาดที่เป็นไปได้
mtraceur

@mtraceur: มันไม่สามารถพกพาทำงานได้เฉพาะใน bash, zsh, ksh (ถ้าสองคำสั่งไม่ได้อยู่ในบรรทัดเดียวกัน) ทำงานอย่างรีบเร่ง, mksh เฉพาะเมื่อมีการโต้ตอบ
cuonglm

@cuongim: ขออภัยฉันอาจจะประมาทเกินไป $_วิธีที่ไม่ได้เป็นแบบพกพาคุณมีสิทธิ setวิธีการทำงานในประไม่ใช่แบบโต้ตอบและมี${1+"$@"}(บวก zsh นามแฝงทั่วโลก) เคล็ดลับที่ควรจะเป็นโดยทั่วไปแม้ว่าฉันคลับคล้ายคลับคลาว่าsetมีประวัติของการไม่ได้อย่างสมบูรณ์แบบพกพาที่มีบางส่วน (เก่า?) เปลือกหอย define-a-variable-hold-the-command-and-then-eval-it วิธีการโดยเฉพาะอย่างยิ่งการใช้การหลบหนีที่เหมาะสมและevalคำสั่งที่เกิดขึ้นจริงโดยทั่วไปจะพกพาได้อย่างสมบูรณ์ตามที่ฉันรู้
mtraceur
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.