grep เอาต์พุตสี: ไม่ใช่ GREP_OPTIONS ไม่ใช่นามแฝง


10

grepฉันต้องการส่งออกสี

.... แต่

  • กลยุทธ์ที่ 1: GREP_OPTIONS แต่นี่เลิกใช้แล้ว ดูhttp://www.gnu.org/software/grep/manual/html_node/Environment-Variables.html
  • Stragegy 2: GREP_COLORS ดูเหมือนโซลูชันตั้งแต่แรกเห็น แต่สิ่งนี้แตกต่าง
  • กลยุทธ์ที่ 3: นามแฝง สิ่งนี้ไม่ได้ผลfind ... | xargs grepเนื่องจาก xargs ไม่ได้ประเมินชื่อแทน
  • กลยุทธ์ที่ 4: เขียนสคริปต์ตัวคลุมแบบเรียบง่าย ไม่ฉันคิดว่านี่สกปรกเกินไปและสร้างปัญหามากกว่าที่จะแก้ไขได้
  • กลยุทธ์ที่ 5: แก้ไขซอร์สโค้ด
  • กลยุทธ์ที่ 6: ติดต่อผู้พัฒนา grep, ขอการเปลี่ยน GREP_OPTIONS
  • กลยุทธ์ NICE-and-EASY: ... นี่หายไป ฉันไม่มีเงื่อนงำ

วิธีแก้ปัญหานี้

ขอบคุณที่พยายามช่วย!

... แต่ฉันไม่สามารถให้รางวัลได้

โทรหาฉันหยาบคาย arogant ดูถูกเหยียดหยาม ....

ฉันเห็นเฉพาะการแก้ไข - ไม่มีวิธีแก้ปัญหา ไม่มีคำตอบที่พอใจคำถาม

ขอบคุณสำหรับความพยายามของคุณ.


1
คุณได้ปฏิเสธคำแนะนำสองข้อเพื่อใช้สคริปต์ตัวตัดคำ (กลยุทธ์ 4 ของคุณ) เป็น "ไม่ใช่คำตอบจริงๆ" คุณสามารถอธิบายสิ่งที่ "สกปรก", "ลำบาก" หรือ "ไม่ใช่คำตอบที่แท้จริง" เกี่ยวกับมันได้หรือไม่? อาจเป็นปัญหาแยกต่างหากที่สามารถแก้ไขได้
JigglyNaga

2
กลยุทธ์ 5 คือแก้ไขซอร์สโค้ดและตั้งcolor_optionเป็น2 ...
don_crissti

2
@JigglyNaga นี่คือคำอธิบายของฉันทำไมสคริปต์ตัวตัดคำไม่ได้แก้ปัญหา ทีมของเราจัดการเซิร์ฟเวอร์หลายเครื่อง น้อยกว่าหนึ่งพันในขณะนี้ แต่จำนวนที่เพิ่มขึ้น ใช่เราใช้การจัดการการกำหนดค่าและมันจะง่ายต่อการปรับใช้สคริปต์กับพวกเขาทั้งหมด แต่ฉันต้องการให้สิ่งต่าง ๆ เป็นเรื่องง่ายและตรงไปตรงมา (คิดถึงสมาชิกใหม่ในทีมฉันไม่ต้องการสับสน) ตัวเลือกที่มีอยู่แล้วค่า--color autoฉันไม่รู้ว่าทำไมคุณไม่สามารถเปิดใช้งานได้ตามค่าเริ่มต้น
guettli

คุณควรใช้กลยุทธ์ 4 หรือ 5 - ฉันต้องการกลยุทธ์ 4 ที่มีสคริปต์ dash / sh น้อยที่สุด ( exec grep --color=auto "$@") หรืออาจเลือกใช้ชื่ออื่น ( grepcหรือcolorgrep) สิ่งนี้มีค่าใช้จ่ายที่ถูกทอดทิ้ง (และไม่มีกระบวนการที่เกิดขึ้นพร้อมกันเป็นพิเศษในขณะทำงาน) เหตุผลที่คุณระบุว่าพวกเขา"ไม่ง่ายพอ"คือข้อเท็จจริงที่ว่าคุณไม่เห็นคุณลักษณะนี้มีประโยชน์มากพอที่จะใช้ความพยายามครั้งเดียว (ค่อนข้างน้อย) ในการติดตั้งใช้งานและกำลังมองหาคนอื่นมาทำแทนคุณ ด้วยเหตุนี้ความเห็น"ไม่ใช่คำตอบ" ของคุณต่อคำตอบที่โพสต์จึงค่อนข้างหยาบ
สัตว์ที่กำหนด

1
@NominalAnimal ใช่คุณพูดถูก "ไม่ใช่คำตอบจริงๆ" ฟังดูหยาบคาย ฉันไม่ใช่เจ้าของภาษา ข้อความใด (การโอนข้อความเดียวกัน) จะดีกว่าไหม
guettli

คำตอบ:


13

เหตุผลบางประการที่ OP ระบุว่าตัวเลือกไม่เหมาะสมไม่มีพื้นฐานในความเป็นจริง ที่นี่ฉันแสดงให้เห็นว่าเอฟเฟ็กต์ชนิดใดที่ใช้กลยุทธ์ของ OP 4:


ในการกระจายส่วนใหญ่grepมีการติดตั้งใน/bin(ทั่วไป) หรือ/usr/bin(OpenSUSE บางทีคนอื่น ๆ ) และเริ่มต้นPATHมี/usr/local/binมาก่อนหรือ/bin /usr/binซึ่งหมายความว่าถ้าคุณสร้าง/usr/local/bin/grepด้วย

#!/bin/sh
exec /bin/grep --color=auto "$@"

โดยที่/bin/shเชลล์ที่ใช้งานร่วมกันได้กับ POSIX ที่จัดจำหน่ายของคุณมักเป็น bash หรือ dash หากgrepอยู่ใน/usr/binให้ทำเช่นนั้น

#!/bin/sh
exec /usr/bin/grep --color=auto "$@"

โอเวอร์เฮดของสคริปต์นี้มีค่าน้อยที่สุด execงบหมายความว่าล่ามสคริปต์ที่จะถูกแทนที่ด้วยgrepไบนารี; นี่หมายความว่าเชลล์ไม่ได้อยู่ในหน่วยความจำในขณะที่grepกำลังดำเนินการ ดังนั้นค่าใช้จ่ายเพียงอย่างเดียวคือการดำเนินการพิเศษของล่ามสคริปต์เช่นเวลาแฝงเล็กน้อยในเวลานาฬิกาแขวน แฝงเป็นค่าคงที่ประมาณ (แตกต่างกันเพียง แต่ขึ้นอยู่กับว่าgrepและshมีอยู่แล้วในแคชหน้าหรือไม่และเกี่ยวกับวิธีการ I / O แบนด์วิดธ์ที่เหลืออยู่) และไม่ได้ขึ้นอยู่กับระยะเวลาที่grepรันหรือเท่าใดข้อมูลจะประมวลผล

ดังนั้นเวลาแฝงนั้นคือค่าใช้จ่ายที่เพิ่มโดยสคริปต์ตัวตัด?

หากต้องการค้นหาให้สร้างสคริปต์ด้านบนและเรียกใช้

time /bin/grep --version
time /usr/local/bin/grep --version

บนเครื่องของฉันอดีตใช้เวลาจริง 0.005 (ข้ามการวิ่งจำนวนมาก) ในขณะที่หลังใช้เวลาจริง 0.006 ดังนั้นค่าใช้จ่ายในการใช้ wrapper ในเครื่องของฉันคือ 0.001s (หรือน้อยกว่า) ต่อการเรียกใช้

นี่คือไม่มีนัยสำคัญ

ฉันยังไม่เห็นอะไร "สกปรก" เกี่ยวกับเรื่องนี้เพราะแอปพลิเคชันและยูทิลิตี้ทั่วไปจำนวนมากใช้วิธีการเดียวกัน หากต้องการดูรายการดังกล่าวในเครื่องของคุณ/binและ/usr/binเพียงเรียกใช้

file /bin/* /usr/bin/* | sed -ne 's/:.*shell script.*$//p'

ในเครื่องของฉันออกดังกล่าวข้างต้นรวมถึงegrep, fgrep, zgrep, which, 7z, chromium-browser, lddและxfigซึ่งผมใช้ค่อนข้างบ่อย ถ้าคุณไม่พิจารณาการแจกจ่ายทั้งหมด "สกปรก" สำหรับการใช้สคริปต์ตัวคลุมคุณไม่มีเหตุผลที่จะต้องพิจารณาสคริปต์ตัวตัดคำ "สกปรก"


เป็นปัญหาเช่นสคริปต์ wrapper อาจทำให้:

หากผู้ใช้มนุษย์เท่านั้น (เมื่อเทียบกับสคริปต์) จะใช้รุ่นของ grep ที่เริ่มต้นที่การสนับสนุนสีถ้ามีการส่งออกไปยังสถานีแล้วสคริปต์กระดาษห่อสามารถตั้งชื่อcolorgrepหรือcgrepหรืออะไรก็ตาม OP เห็นสมควร

สิ่งนี้จะหลีกเลี่ยงปัญหาความเข้ากันได้ที่เป็นไปได้ทั้งหมดเนื่องจากพฤติกรรมของgrepไม่เปลี่ยนแปลงเลย


การเปิดใช้งานgrepตัวเลือกด้วยสคริปต์ตัวตัดคำ แต่ในวิธีที่หลีกเลี่ยงปัญหาใหม่:

เราสามารถเขียนสคริปต์ตัวตัดใหม่เพื่อสนับสนุนการกำหนดเองได้อย่างง่ายดายGREP_OPTSแม้ว่าGREP_OPTIONSจะไม่ได้รับการสนับสนุน (เนื่องจากเลิกใช้แล้ว) วิธีนี้ผู้ใช้สามารถเพิ่มexport "GREP_OPTIONS=--color=auto"หรือคล้ายกับโปรไฟล์ของพวกเขา /usr/local/bin/grepเป็นแล้ว

#!/bin/sh
exec /bin/grep $GREP_OPTIONS "$@"

โปรดทราบว่าไม่มีเครื่องหมายคำพูดล้อมรอบ$GREP_OPTIONSเพื่อให้ผู้ใช้สามารถระบุมากกว่าหนึ่งตัวเลือก

ในระบบของฉันการรันtime /usr/local/bin/grep --versionด้วยGREP_OPTIONSempty หรือด้วยGREP_OPTIONS=--color=autoนั้นเร็วเท่ากับเวอร์ชันก่อนหน้าของ wrapper script grepคือมักจะใช้เวลาหนึ่งมิลลิวินาทีนานในการดำเนินการกว่าธรรมดา

รุ่นล่าสุดนี้เป็นรุ่นที่ฉันแนะนำให้ใช้เป็นการส่วนตัว


โดยสรุปกลยุทธ์ของ OP 4:

  • เป็นสิ่งที่แนะนำโดยgrepนักพัฒนา

  • เป็นเรื่องเล็กน้อยที่จะใช้ (สองบรรทัด)

  • มีค่าใช้จ่ายที่ไม่มีนัยสำคัญ (ความล่าช้าพิเศษหนึ่งมิลลิวินาทีต่อการเรียกใช้บนแล็ปท็อปเครื่องนี้โดยเฉพาะตรวจสอบได้ง่ายในแต่ละเครื่อง)

  • สามารถนำมาใช้เป็นสคริปต์ wrapper ที่เพิ่มGREP_OPTSการสนับสนุน (เพื่อแทนที่เลิก / ไม่สนับสนุนGREP_OPTIONS)

  • สามารถนำไปใช้ (เป็นcolorgrep/ cgrep) ที่ไม่มีผลกับสคริปต์หรือผู้ใช้ที่มีอยู่เลย

เพราะมันเป็นเทคนิคที่ใช้กันอย่างแพร่หลายในการแจกแจงลินุกซ์แล้วมันเป็นเทคนิคทั่วไปและไม่ "สกปรก"

หากมีการใช้งานเป็น wrapper ( colorgrep/ cgrep) แยกต่างหากมันจะไม่สามารถสร้างปัญหาใหม่ได้เนื่องจากจะไม่มีผลgrepกับพฤติกรรมเลย หากนำมาใช้เป็นสคริปต์เสื้อคลุมที่เพิ่มGREP_OPTSการสนับสนุนการใช้GREP_OPTS=--color=autoมีตรงความเสี่ยงเดียวกัน (WRT. ปัญหากับสคริปต์ที่มีอยู่) ที่ต้นน้ำเพิ่มค่าเริ่มต้น--color=autoจะ ดังนั้นความคิดเห็นที่ว่า "การสร้างปัญหามากกว่าที่แก้" ไม่ถูกต้องสมบูรณ์: ไม่มีการสร้างปัญหาเพิ่มเติม


3

เอกสารที่คุณให้ไว้กับกลยุทธ์แรกพูดว่า:

โปรดใช้นามแฝงหรือสคริปต์แทน ตัวอย่างเช่นหาก grep อยู่ในไดเรกทอรี '/ usr / bin' คุณสามารถเพิ่ม $ HOME / bin ไปที่ PATH ของคุณและสร้างสคริปต์ที่เรียกใช้งานได้ $ HOME / bin / grep ที่มีสิ่งต่อไปนี้:

#! /bin/sh
export PATH=/usr/bin
exec grep --color=auto --devices=skip "$@"

ดังนั้นหากนามแฝงเป็นไปไม่ได้สำหรับคุณสคริปต์ตัวตัดคำเป็นวิธีเดียว


นั่นคือกลยุทธ์ 4 ... ไม่ใช่คำตอบจริงๆ
guettli

3

สาเหตุที่ทำให้GREP_OPTIONSตัวแปรไม่ได้รับการยอมรับคือมันมีแนวโน้มที่จะทำให้เกิดปัญหาเมื่อgrepมีการเรียกบางแห่งในสคริปต์และสคริปต์ไม่ทำงานกับตัวเลือกอื่นที่มาจากตัวแปร หากคุณเขียนสคริปต์ตัวตัดคำเพื่อแสดงgrepว่าคุณมีปัญหาเดียวกันเว้นแต่คุณตั้งชื่ออื่น

$ cat ~/bin/cgrep
#!/bin/sh
exec grep --color=always "$@"
$ find  -exec cgrep  {} +

หรือเก็บตัวเลือกที่คุณชื่นชอบไว้ในตัวแปร ในเชลล์อื่นที่ไม่ใช่ zsh นี่เป็นเรื่องยุ่งยากหากตัวเลือกมีอักขระไวด์การ์ด ( \[*?) แต่อย่างอื่นคุณสามารถใช้ตัวแปร unquote เพื่อรับคำสั่งด้วยอาร์กิวเมนต์

cgrep=(grep --color=always)
find  -exec $cgrep  {} +

โปรดทราบว่า GNU และ BSD grep สามารถประมวลผลแผนผังไดเรกทอรีซ้ำซึ่งช่วยลดความจำเป็นfindในการใช้ร่วมกับgrepเวลาส่วนใหญ่


1
นั่นคือกลยุทธ์ 4 ... ไม่ใช่คำตอบจริงๆ
guettli

@guettli นั่นคือคำตอบที่ถูกต้อง หากคุณต้องการคำสั่งที่มีพฤติกรรมแตกต่างกันgrepคุณจำเป็นต้องมีคำสั่งที่มีชื่อแตกต่างกันหรืออื่น ๆ หากคุณใช้ชื่อเดิมคุณจะต้องแตกสคริปต์ที่คาดว่าจะมีพฤติกรรมแบบดั้งเดิม / มาตรฐาน นั่นคือที่สะอาดและไม่ก่อให้เกิดปัญหาเพิ่มเติม
Stéphane Chazelas

@ StéphaneChazelasใช่คุณพูดถูก นี่คือคำตอบที่ถูกต้องตามมุมมองของคุณ
guettli

1

สิ่งที่ง่ายที่สุดคือใช้นามแฝง (กลยุทธ์ 3) หากคุณสนใจxargsคำสั่งจริงๆคุณยังสามารถแทนที่ด้วยคำสั่ง bash

alias grep='grep --color'
xargs() {
    local args
    for ((i=1; i<=$#; i++))
    do
            if [[ "-E -L -P -I -s -d" == *"${!i}"* ]]; then
                    ((i=i+1))
            elif [[ ${!i:0:1} != "-" ]]; then
                    if [[ ${!i} == "grep" ]]; then
                            args="--color"
                    fi
                    /usr/bin/xargs ${@:1:i} $args ${@:i+1}
                    return;
            fi
    done
}

แต่สิ่งนี้ไม่ดีไปกว่าการใช้คำสั่ง wrapper ซึ่งดูเหมือนว่าจะเป็นคำแนะนำที่grepทีมแนะนำ:

/usr/local/bin/grep:

#!/bin/bash
/bin/grep --color "$@"

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

มันจะค่อนข้างง่ายสำหรับพวกเขาที่จะเปิดใช้งานโดยค่าเริ่มต้นcolorตัวเลือกหรือเมื่อGREP_COLORSได้รับการตั้งค่า


1
ขอบคุณสำหรับ "... คุณควรติดต่อทีมนักพัฒนา grep ... " สิ่งนี้ทำให้ฉันตอบรับเชิงบวก ตอนนี้ฉันรู้แล้วว่าฉันไม่ใช่คนเดียวที่คิดว่ามีบางอย่างขาดหายไปที่นี่
guettli

ฉันได้เพิ่มความคิดเห็นของคุณ "... คุณควรติดต่อทีมพัฒนา grep ... " เป็น strategy6 ในคำถาม ถึงตอนนี้นี่คือคำตอบที่ฉันโปรดปราน
guettli

0

นี่เป็นวิธีการแก้ปัญหาจากคำตอบยอดนิยมโดย @NominalAnimal แต่มีgrep: ...คำเตือนในปกติ(แทน/bin/grep: ...):

#!/bin/bash
exec -a grep /bin/grep --color=auto "$@"

ฉันรู้วิธีเขียนตัวห่อ wrapper ไม่ใช่วิธีแก้ปัญหาในบริบทนี้
guettli

@guettli เอาล่ะคำตอบไม่ได้หมายถึงสถานการณ์ของคุณอย่างแม่นยำ ... หากความคิดเห็นมีฟีเจอร์การจัดรูปแบบเหมือนกับคำตอบนั่นจะเป็นความคิดเห็น (และฉันมีการแก้ไขที่คล้ายกันที่ถูกปฏิเสธโดยผู้เขียนต้นฉบับหรือบางสิ่ง) ไม่ได้สำหรับสถานการณ์ของคุณฉันคิดว่าคำตอบที่แท้จริงสำหรับคำถามของคุณคือ: ไม่มี "กลยุทธ์ที่ดีและง่าย" ไม่มีอยู่จริง
Kirill Bulygin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.