ฉันมีจำนวนบรรทัดที่ดึงมาจากไฟล์หลังจากรันคำสั่งgrepดังนี้:
var=`grep xyz abc.txt`
สมมติว่าฉันได้ 10 บรรทัดซึ่งประกอบด้วย xyz เป็นผลลัพธ์
ตอนนี้ฉันต้องประมวลผลแต่ละบรรทัดที่ฉันได้รับจากคำสั่ง grep ฉันจะดำเนินการสิ่งนี้ได้อย่างไร
ฉันมีจำนวนบรรทัดที่ดึงมาจากไฟล์หลังจากรันคำสั่งgrepดังนี้:
var=`grep xyz abc.txt`
สมมติว่าฉันได้ 10 บรรทัดซึ่งประกอบด้วย xyz เป็นผลลัพธ์
ตอนนี้ฉันต้องประมวลผลแต่ละบรรทัดที่ฉันได้รับจากคำสั่ง grep ฉันจะดำเนินการสิ่งนี้ได้อย่างไร
คำตอบ:
วิธีง่าย ๆ วิธีหนึ่งคือไม่เก็บผลลัพธ์ในตัวแปร แต่วนซ้ำโดยตรงกับมันด้วย while / read loop
สิ่งที่ต้องการ:
grep xyz abc.txt | while read -r line ; do
echo "Processing $line"
# your code goes here
done
มีการเปลี่ยนแปลงในรูปแบบนี้ขึ้นอยู่กับสิ่งที่คุณหลังจาก
หากคุณต้องการเปลี่ยนตัวแปรภายในลูป (และให้เห็นการเปลี่ยนแปลงนั้นนอก) คุณสามารถใช้การทดแทนกระบวนการตามที่ระบุไว้ในคำตอบของ fedorqui :
while read -r line ; do
echo "Processing $line"
# your code goes here
done < <(grep xyz abc.txt)
while read p || [[ -n $p ]]; do ...
(ยืมจากstackoverflow.com/questions/1521462/ … )
คุณสามารถทำwhile read
ลูปต่อไปนี้ซึ่งจะถูกป้อนด้วยผลลัพธ์ของgrep
คำสั่งโดยใช้การทดแทนกระบวนการที่เรียกว่า:
while IFS= read -r result
do
#whatever with value $result
done < <(grep "xyz" abc.txt)
ด้วยวิธีนี้คุณไม่จำเป็นต้องเก็บผลลัพธ์ไว้ในตัวแปร แต่จะ "ส่ง" ผลลัพธ์ไปยังลูปโดยตรง
บันทึกการใช้งานIFS=
และread -r
ตามคำแนะนำใน BashFAQ / 001: ฉันจะอ่านไฟล์ (data stream, variable) แบบ line-by-line (และ / หรือ field-by-field) ได้อย่างไร? :
อ็อพชัน -r เพื่ออ่านป้องกันการตีความเครื่องหมายทับขวา (โดยปกติจะใช้เป็นคู่ของเครื่องหมายทับขวาของบรรทัดใหม่เพื่อดำเนินการต่อผ่านหลายบรรทัดหรือเพื่อหลีกเลี่ยงตัวคั่น) หากไม่มีตัวเลือกนี้แบ็กสแลชที่ไม่ใช้ค่า Escape ใด ๆ ในอินพุตจะถูกยกเลิก คุณควรใช้ตัวเลือก -r กับการอ่านเกือบทุกครั้ง
ในสถานการณ์ข้างต้น IFS = ป้องกันการตัดส่วนของช่องว่างนำหน้าและต่อท้าย ลบออกหากคุณต้องการผลกระทบนี้
เกี่ยวกับการทดแทนกระบวนการอธิบายในหน้าทุบตีแฮกเกอร์ :
การทดแทนกระบวนการเป็นรูปแบบของการเปลี่ยนเส้นทางที่อินพุตหรือเอาต์พุตของกระบวนการ (ลำดับของคำสั่งบางอย่าง) ปรากฏเป็นไฟล์ชั่วคราว
for
รุ่น พยายามทำวนซ้ำ"${$(grep xyz abc.txt)[@]}"
ในstackoverflow.com/a/14588210/1983854แต่ทำไม่ได้ ดังนั้นฉันเพิ่งออกจากรุ่นแรก
zsh
ซึ่งการทำรังแบบนั้นอาจใช้งานได้)
while IFS= read -r result <&3
และdone 3< <(grep ...
ฉันขอแนะนำให้ใช้ awk แทน grep + อย่างอื่นที่นี่
awk '$0~/xyz/{ //your code goes here}' abc.txt
//your code goes here
อย่างไร
ไม่มีการวนซ้ำใด ๆ ด้วยตัวเลือก grep --line ที่บัฟเฟอร์:
your_command | grep --line-buffered "your search"
ตัวอย่างชีวิตจริงด้วย ouf คำสั่ง debug เราเตอร์ Symfony PHP Framework, เพื่อ grep เส้นทางที่เกี่ยวข้อง "api" ทั้งหมด:
php bin/console d:r | grep --line-buffered "api"
tail -f some.log
ในกรณีของฉัน) ...
บ่อยครั้งที่ลำดับของการประมวลผลไม่สำคัญ GNU Parallel ถูกสร้างขึ้นสำหรับสถานการณ์นี้:
grep xyz abc.txt | parallel echo do stuff to {}
หากคุณกำลังดำเนินการเช่น:
grep xyz abc.txt | myprogram_reading_from_stdin
และmyprogram
ช้าแล้วคุณสามารถเรียกใช้:
grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin
ทำซ้ำผลลัพธ์ grep ด้วย while / read loop ชอบ:
grep pattern filename.txt | while read -r line ; do
echo "Matched Line: $line"
# your code goes here
done
สำหรับผู้ที่กำลังมองหาหนึ่งซับ:
grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
grep -o
ของสิ่งนี้ การ-o
ตั้งค่าสถานะจะให้เฉพาะข้อความที่ตรงกับหนึ่งตรงต่อบรรทัดของผลลัพธ์ (มันไม่ครบถ้วนดังนั้นecho aaa |grep 'a*'
ให้ "aaa" และละเว้นการจับคู่สามส่วนเท่านั้น "", "a" และ "aa")