ฉันควรใช้การเปลี่ยนเส้นทางอินพุตเมื่อใด


21

ฉันใช้สองคำสั่งต่อไปนี้เพื่อสร้างผลลัพธ์เดียวกัน: -

[root@localhost ~]# grep line comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

[root@localhost ~]# grep line <comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

ได้โปรดอธิบายให้ฉันทราบถึงข้อดี / ข้อเสียใด ๆ หากวิธีการใดวิธีหนึ่งในสองวิธีนี้เหนือกัน

คำตอบ:


28

จากman grepหน้า (บน Debian):

รายละเอียด

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.

ในกรณีแรกให้grepเปิดไฟล์ ในครั้งที่สองเชลล์เปิดไฟล์และกำหนดให้กับอินพุตมาตรฐานของgrepและgrepไม่ถูกส่งผ่านอาร์กิวเมนต์ชื่อไฟล์ใด ๆ สมมติว่าจำเป็นต้อง grep อินพุตมาตรฐาน

ข้อดีของ 1:

  • grep สามารถ grep มากกว่าหนึ่งไฟล์ได้
  • grepสามารถแสดงชื่อไฟล์ที่แต่ละครั้งที่lineพบ

ข้อดีของ 2:

  • หากไม่สามารถเปิดไฟล์ได้เชลล์จะส่งคืนข้อผิดพลาดซึ่งจะรวมข้อมูลที่เกี่ยวข้องมากขึ้น (เช่นหมายเลขบรรทัดในสคริปต์) และในวิธีที่สอดคล้องกันมากขึ้น (ถ้าคุณปล่อยให้เชลล์เปิดไฟล์สำหรับคำสั่งอื่นด้วย) grepเปิดมัน และหากไฟล์ไม่สามารถเปิดgrepได้จะไม่มีการเรียกใช้ (ซึ่งสำหรับบางคำสั่ง - อาจจะไม่ใช่grep- สามารถสร้างความแตกต่างได้มาก)
  • ในgrep line < in > outหากinไม่สามารถเปิดoutได้จะไม่ถูกสร้างหรือตัดทอน
  • ไม่มีปัญหากับไฟล์บางไฟล์ที่มีชื่อผิดปกติ (เช่น-หรือชื่อไฟล์ที่ขึ้นต้นด้วย-) ²
  • cosmetic: คุณสามารถวาง<fileที่ใดก็ได้บนบรรทัดคำสั่งเพื่อแสดงโฟลว์คำสั่งตามธรรมชาติเช่น<in grep line >outถ้าคุณต้องการ
  • cosmetic: ด้วย GNU grepคุณสามารถเลือกฉลากที่จะใช้ด้านหน้าของบรรทัดที่ตรงกันแทนชื่อไฟล์เช่นเดียวกับใน:

    <file grep --label='Found in file at line' -Hn line
    

ในแง่ของประสิทธิภาพหากไม่สามารถเปิดไฟล์ได้คุณบันทึกการทำงานgrepเมื่อใช้การเปลี่ยนเส้นทาง แต่อย่างอื่นสำหรับgrepฉันไม่ได้คาดหวังความแตกต่างมากนัก

ด้วยการเปลี่ยนเส้นทางคุณจะไม่ต้องทะเลาะโต้เถียงกันอีกgrepแล้วทำให้การgrepแยกวิเคราะห์ง่ายขึ้นเล็กน้อย ในอีกทางหนึ่งเชลล์จะต้องการ (อย่างน้อย) การเรียกใช้ระบบเพิ่มเติมไปdup2()ยัง file descriptor ไปยัง file descriptor 0

ใน{ grep -m1 line; next command; } < file, grep(ที่นี่ GNU grep) จะต้องการที่จะseek()กลับไปหลังจากการจับคู่สายเพื่อให้next commandเห็นส่วนที่เหลือของไฟล์ (มันยังจะต้องตรวจสอบว่าไฟล์เป็น seekable หรือไม่) กล่าวอีกนัยหนึ่งตำแหน่งภายใน stdin คือgrepผลลัพธ์อีกตัวหนึ่งของ ด้วยgrep -m1 line fileก็สามารถเพิ่มประสิทธิภาพให้เห็นว่าที่สิ่งที่น้อยกว่าหนึ่งgrepในการดูแลเกี่ยวกับ


หมายเหตุ

¹ด้วยzshคุณสามารถทำได้:

grep line < file1 < file2

แต่นั่นเป็นการทำงานที่เทียบเท่าcat file1 file2 | grep line(โดยไม่ต้องเรียกใช้catยูทิลิตี้) และมีประสิทธิภาพน้อยกว่านั้นอาจทำให้เกิดความสับสนหากไฟล์แรกไม่ได้ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่และจะไม่แจ้งให้คุณทราบว่าไฟล์ใดที่พบรูปแบบ

²ในกรณีksh93และbashแม้ว่าจะมีไฟล์เช่น /dev/tcp/host/port(และ/dev/fd/xในบางระบบbash) ซึ่งเมื่อใช้ในเป้าหมายของการเปลี่ยนเส้นทางเชลล์จะถูกสกัดกั้นเพื่อวัตถุประสงค์พิเศษแทนที่จะเปิดไฟล์บนระบบไฟล์จริงๆ (แม้ว่าโดยทั่วไปจะเป็นไฟล์เหล่านั้น ไม่มีอยู่ในระบบไฟล์) /dev/stdinจุดมุ่งหมายเดียวกับที่-ได้รับการยอมรับโดยgrepแต่อย่างน้อยนี่ก็ namespaced ถูกกว่า (ใคร ๆ ก็สามารถสร้างไฟล์ชื่อ-ในไดเรกทอรีใด ๆ ในขณะที่ผู้ดูแลระบบเท่านั้นสามารถสร้างไฟล์ที่เรียกว่า/dev/tcp/host/portและผู้บริหารควรรู้ดีกว่า)


+1 สำหรับคำอธิบายที่ดี ฉันมีหนึ่งข้อสงสัย: ในกรณีที่ 2 เมื่อเชลล์เปิดไฟล์มันส่งเนื้อหาไฟล์ที่เปิดไปยังอินพุตมาตรฐาน (คีย์บอร์ด) หรือไม่? (ฉันสับสนกับคำว่า 'อินพุตมาตรฐานของ grep')
Ankit

1
@Ankit, stdin เป็นที่ที่แอปพลิเคชันอ่านอินพุตตามค่าเริ่มต้นตัวอธิบายไฟล์ 0 เมื่ออยู่ในเทอร์มินัล fd 0 จะถูกเปิดจากการอ่านบนอุปกรณ์เทอร์มินัล (เช่น / dev / ttyxx หรือ / dev / pts / n) นั่นคือวิธีที่พวกเขาได้รับสิ่งที่คุณพิมพ์บนแป้นพิมพ์ การเปลี่ยนเส้นทางของเชลล์ของคำสั่ง stdin เพียงแค่เปิด fd 0 ไปยังไฟล์อื่นก่อนที่จะดำเนินการคำสั่ง
Stéphane Chazelas

6

คำตอบโดย StephaneChazelas ครอบคลุมgrep(1)และคำสั่งเชื้อสาย Unix ส่วนใหญ่ทำงานในลักษณะนั้น แต่ไม่ใช่ทั้งหมด มันเป็นมาตรฐานในการอ่านอย่างใดอย่างหนึ่งจากการป้อนข้อมูลมาตรฐาน (จากแป้นพิมพ์จากไฟล์เปลี่ยนเส้นทางผ่าน< fileหรือจากการส่งออกประปาโดยคำสั่งอื่นตัวอย่างโง่ls * | grep '^ab*c$') หรือจากไฟล์ (s) grep comment file1 file2 file3ได้รับเป็นข้อโต้แย้งเช่น คำสั่งบางคนใช้การประชุมมีที่ไฟล์ชื่อ-คือเข้ามาตรฐานเพื่อให้คุณสามารถพูดได้ว่าmake-middle | cat head - tailจะได้รับกระแสกับheadสิ่งที่สร้างตามด้วยgen-middle tailนี่คือโดยการออกแบบเพื่อให้ความยืดหยุ่นในการใช้คำสั่ง

ไหนดีกว่ากัน ตราบใดที่การทำงานcmd fileสั้นกว่าcmd < file; อาจมีความแตกต่างเล็กน้อยในช่วงเวลาระหว่างเชลล์ที่ทำไฟล์ frobbing ( <) และคำสั่งที่ทำด้วยตัวเอง แต่อาจไม่สามารถสังเกตเห็นได้เว้นแต่คุณจะไม่ทำอะไรเลยตลอดวัน มันจะขึ้นอยู่กับการพิจารณาเช่นข้อดีที่กล่าวถึงในคำตอบของ Stephane


cmd fileไม่สั้นกว่าcmd<fileนี้
Stéphane Chazelas

มันเป็นหนึ่งในkeystrokeสั้นแม้ว่าทะนงคุณจะต้องกด Shift <เพื่อพิมพ์
DopeGhoti
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.