เมื่อคุณขึ้นไปถึงคอใน alligators มันง่ายที่จะลืมว่าเป้าหมายคือการระบายหนอง
- คำพูดยอดนิยม
คำถามเกี่ยวกับ echo
และยังมีคำตอบส่วนใหญ่ที่มุ่งเน้นไปที่วิธีการแอบset +x
สั่งให้มีวิธีแก้ปัญหาที่ง่ายกว่าและตรงกว่า:
{ echo "Message"; } 2> /dev/null
(ฉันยอมรับว่าฉันอาจไม่ได้คิด{ …; } 2> /dev/null
ว่าฉันไม่ได้เห็นคำตอบก่อนหน้านี้หรือไม่)
มันค่อนข้างยุ่งยาก แต่ถ้าคุณมีบล็อกติดต่อกัน echo
คำสั่งคุณไม่จำเป็นต้องทำทีละคำ:
{
echo "The quick brown fox"
echo "jumps over the lazy dog."
} 2> /dev/null
โปรดทราบว่าคุณไม่จำเป็นต้องใช้เครื่องหมายอัฒภาคเมื่อคุณมีการขึ้นบรรทัดใหม่
คุณสามารถลดภาระการพิมพ์โดยใช้แนวคิดของ kenorb ใน
การเปิด/dev/null
อย่างถาวรบนตัวอธิบายไฟล์ที่ไม่ได้มาตรฐาน (เช่น 3) จากนั้นพูด2>&3
แทน2> /dev/null
ตลอดเวลา
สี่คำตอบแรกในขณะที่เขียนนี้ต้องทำอะไรเป็นพิเศษ (และในกรณีส่วนใหญ่ยุ่งยาก)
ทุกecho
ครั้งที่คุณทำ หากคุณต้องการให้ทุก echo
คำสั่งระงับการติดตามการเรียกใช้งาน (และทำไมคุณไม่ลองใช้) คุณสามารถทำได้ทั่วโลกโดยไม่ต้องใส่รหัสจำนวนมาก ก่อนอื่นฉันสังเกตว่านามแฝงไม่ได้ติดตาม:
$ myfunc()
> {
> date
> }
$ alias myalias="date"
$ set -x
$ date
+ date
Mon, Oct 31, 2016 0:00:00 AM # Happy Halloween!
$ myfunc
+ myfunc # Note that function call is traced.
+ date
Mon, Oct 31, 2016 0:00:01 AM
$ myalias
+ date # Note that it doesn’t say + myalias
Mon, Oct 31, 2016 0:00:02 AM
(โปรดทราบว่าตัวอย่างของสคริปต์ต่อไปนี้จะทำงานถ้า Shebang คือ#!/bin/sh
แม้ว่า/bin/sh
จะเป็นลิงก์ไปยัง bash แต่ถ้าเป็น Shebang #!/bin/bash
คุณต้องเพิ่มshopt -s expand_aliases
คำสั่งเพื่อให้ aliases ทำงานในสคริปต์)
ดังนั้นสำหรับเคล็ดลับแรกของฉัน:
alias echo='{ set +x; } 2> /dev/null; builtin echo'
ตอนนี้เมื่อเราพูดว่าecho "Message"
เรากำลังเรียกนามแฝงซึ่งไม่ได้ติดตาม นามแฝงจะปิดตัวเลือกการติดตามในขณะที่ระงับข้อความการติดตามจากset
คำสั่ง (ใช้เทคนิคที่แสดงครั้งแรกในคำตอบของผู้ใช้ 5071535 ) แล้วดำเนินการecho
คำสั่งจริง สิ่งนี้ทำให้เราได้ผลคล้ายกับคำตอบของผู้ใช้ 5071535 โดยไม่จำเป็นต้องแก้ไขโค้ดในทุก echo
คำสั่ง อย่างไรก็ตามโหมดนี้จะปิดโหมดการติดตาม เราไม่สามารถใส่ a set -x
alias (หรืออย่างน้อยก็ไม่ง่าย) เพราะ alias อนุญาตให้ใช้สตริงแทนคำได้ ไม่มีส่วนของสตริงนามแฝงใด ๆ ที่สามารถถูกฉีดเข้าไปในคำสั่ง
หลังจากอาร์กิวเมนต์ (เช่น, "Message"
) ตัวอย่างเช่นหากสคริปต์มี
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
date
ผลลัพธ์จะเป็น
+ date
Mon, Oct 31, 2016 0:00:03 AM
The quick brown fox
jumps over the lazy dog.
Mon, Oct 31, 2016 0:00:04 AM # Note that it doesn’t say + date
ดังนั้นคุณยังต้องเปิดใช้งานตัวเลือกการติดตามอีกครั้งหลังจากแสดงข้อความ - แต่เพียงครั้งเดียวหลังจากบล็อกecho
คำสั่งต่อเนื่องทุกบล็อก :
date
echo "The quick brown fox"
echo "jumps over the lazy dog."
set -x
date
มันจะดีถ้าเราสามารถสร้างset -x
อัตโนมัติหลังจากecho
- และเราทำได้โดยใช้กลอุบายเพิ่มเติม แต่ก่อนที่ฉันจะนำเสนอให้พิจารณาสิ่งนี้ OP เริ่มต้นด้วยสคริปต์ที่ใช้#!/bin/sh -ex
Shebang ผู้ใช้สามารถลบออกx
จาก shebang โดยปริยายและมีสคริปต์ที่ทำงานได้ตามปกติโดยไม่ต้องมีการติดตามการเรียกใช้งาน มันจะดีถ้าเราสามารถพัฒนาวิธีแก้ปัญหาที่รักษาคุณสมบัตินั้นไว้ คำตอบแรก ๆ ที่นี่ล้มเหลวเนื่องจากคุณสมบัตินั้นเปิดใช้งานการติดตาม“ ย้อนกลับ” หลังจากecho
คำสั่งโดยไม่มีเงื่อนไขโดยไม่คำนึงว่ามันเปิดอยู่แล้วหรือไม่
คำตอบนี้อย่างเด่นชัดล้มเหลวในการรับรู้ปัญหาที่มันเข้ามาแทนที่ echo
เอาต์พุตพร้อมเอาต์พุตการติดตาม ดังนั้นข้อความทั้งหมดจะหายไปหากการติดตามถูกปิด ตอนนี้ฉันจะนำเสนอทางออกที่เปิดการสืบค้นกลับหลังจากecho
คำสั่งแบบมีเงื่อนไข - เฉพาะเมื่อเปิดใช้แล้ว การลดระดับเป็นโซลูชันที่เปลี่ยนการติดตาม“ ย้อนกลับ” โดยไม่มีเงื่อนไขนั้นเป็นเรื่องเล็กน้อยและถูกทิ้งไว้เป็นแบบฝึกหัด
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
echo_and_restore() {
builtin echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
$-
เป็นรายการตัวเลือก การต่อตัวอักษรที่สอดคล้องกับตัวเลือกทั้งหมดที่ตั้งค่าไว้ ตัวอย่างเช่นถ้าe
และx
ตัวเลือกที่มีการตั้งค่าจากนั้น$-
จะมีการสับสนของตัวอักษรที่มีและe
x
นามแฝงใหม่ของฉัน (ด้านบน) บันทึกค่า$-
ก่อนปิดการติดตาม จากนั้นเมื่อปิดการติดตามแล้วจะส่งการควบคุมไปยังฟังก์ชันเชลล์ ฟังก์ชั่นนั้นทำจริงecho
แล้วตรวจสอบเพื่อดูว่ามีการx
เปิดตัวเลือกเมื่อนามแฝงถูกเรียกใช้หรือไม่ หากเปิดใช้ตัวเลือกฟังก์ชันจะเปิดขึ้นมาใหม่ ถ้าปิดอยู่ฟังก์ชันจะปิด
คุณสามารถแทรกเจ็ดบรรทัดข้างต้น (แปดถ้าคุณมีshopt
) ที่จุดเริ่มต้นของสคริปต์และปล่อยให้ส่วนที่เหลืออยู่คนเดียว
สิ่งนี้จะช่วยให้คุณ
- เพื่อใช้บรรทัด shebang ต่อไปนี้:
#! / bin / sh -ex
#! / bin / sh -e
#! / bin / sh –x
หรือเพียงแค่ธรรมดา#! / bin / ดวลจุดโทษ
และควรทำงานตามที่คาดไว้
- มีรหัสเช่น
(shebang)
คำสั่ง1
คำสั่ง2
คำสั่ง3
ชุด -x
คำสั่ง4
คำสั่ง5
คำสั่ง6
ชุด + x
คำสั่ง7
คำสั่ง8
คำสั่ง9
และ
- คำสั่ง 4, 5 และ 6 จะถูกติดตาม - เว้นแต่ว่าหนึ่งในนั้นคือ
echo
ในกรณีนี้จะถูกดำเนินการ แต่ไม่ได้ติดตาม (แม้ว่าคำสั่ง 5 จะเป็นecho
คำสั่ง 6 จะยังคงติดตามอยู่)
- คำสั่ง 7, 8 และ 9 จะไม่ถูกติดตาม แม้ว่าคำสั่ง 8 จะเป็น
echo
คำสั่ง 9 ยังคงไม่ถูกติดตาม
- คำสั่งที่ 1, 2 และ 3 จะได้รับการตรวจสอบ (เช่น 4, 5 และ 6) หรือไม่ (เช่น 7, 8 และ 9) ขึ้นอยู่กับว่า shebang
x
รวมถึง
ป.ล. ฉันค้นพบว่าในระบบของฉันฉันสามารถทิ้งbuiltin
คำหลักไว้ในคำตอบตรงกลาง (อันที่เป็นเพียงนามแฝงecho
) ไม่น่าแปลกใจเลย bash (1) บอกว่าระหว่างการขยายนามแฝง ...
... คำที่เหมือนกับนามแฝงที่กำลังขยายจะไม่ถูกขยายอีกเป็นครั้งที่สอง ซึ่งหมายความว่าที่หนึ่งอาจนามแฝงls
ไปls -F
เช่นทุบตีและไม่พยายามที่จะขยายซ้ำข้อความทดแทน
ไม่น่าแปลกใจมากเกินไปคำตอบสุดท้าย (หนึ่งด้วยecho_and_restore
) ล้มเหลวหากbuiltin
คำหลักที่ถูกละ1 แต่แปลกที่มันทำงานถ้าฉันลบbuiltin
และเปลี่ยนคำสั่ง:
echo_and_restore() {
echo "$*"
case "$save_flags" in
(*x*) set -x
esac
}
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
__________
1 ดูเหมือนจะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนด ฉันเคยเห็น
- วงวนไม่สิ้นสุด (อาจเป็นเพราะการเรียกซ้ำแบบไม่ จำกัด )
/dev/null: Bad address
ข้อผิดพลาดและ
- การถ่ายโอนข้อมูลหลัก
echo +x; echo "$*"; echo -x
ในนามแฝงฉันต้องการที่จะเห็นมัน