grep กับตัวแปร


58

สมมติว่าฉันมีตัวแปร

line="This is where we select from a table."

ตอนนี้ฉันต้องการ grep เลือกกี่ครั้งเกิดขึ้นในประโยค

grep -ci "select" $line

ฉันลองมัน แต่มันใช้งานไม่ได้ ฉันก็ลอง

grep -ci "select" "$line"

มันยังไม่ทำงาน ฉันได้รับข้อผิดพลาดดังต่อไปนี้

grep: This is where we select from a table.: No such file or directory

1
คุณจำเป็นต้องใช้ ...<<<"$line" herestring คำสั่งgrepคาดว่าจะมีไฟล์แทน
Valentin Bajrami

คำตอบ:


84

ได้grepอ่านบนเข้ามาตรฐาน คุณไปใช้ท่อ ...

$ echo "$line" | grep select

... หรือสตริงที่นี่ ...

$ grep select <<< "$line"

นอกจากนี้คุณอาจต้องการแทนที่ช่องว่างด้วยการขึ้นบรรทัดใหม่ก่อน grepping:

$ echo "$line" | tr ' ' '\n' | grep select

... หรือคุณสามารถขอgrepให้พิมพ์เฉพาะการแข่งขัน:

$ echo "$line" | grep -o select

สิ่งนี้จะช่วยให้คุณกำจัดส่วนที่เหลือเมื่อมีการแข่งขัน

แก้ไข:โอ๊ะอ่านเล็ก ๆ น้อย ๆ เร็วเกินไปขอบคุณมาร์โก เพื่อนับเหตุการณ์ที่เกิดขึ้นเพียงท่อใด ๆ ของสิ่งเหล่านี้เพื่อwc(1);)

แก้ไขอีกทำหลังจากlzkataความคิดเห็นของข้อความเมื่อใช้$lineecho


3
เนื่องจาก OP ต้องการนับจำนวนการเกิดขึ้นของสตริงคุณสามารถเพิ่ม a wcเพื่อทำงานให้เสร็จสมบูรณ์:grep -o <string> <<< "$variable" | wc -l
Marco

2
ใช้echo "$line"เพื่อรักษาบรรทัดใหม่ที่มีอยู่แทนที่จะสร้างด้วยtr
Izkata

ความพร้อมใช้งานของ Here String คืออะไร มันต้องการ Bash หรือเชลล์อื่นหรือไม่?

ตามวิกิพีเดียสตริงที่นี่มีอยู่ใน bash, ksh และ zsh (แต่ฉันคิดว่าอาจจะมีคนอื่น)
John WH Smith

7
test=$line i=0
while case "$test" in (*select*)
test=${test#*select};;(*) ! :;;
esac; do i=$(($i+1)); done

คุณไม่จำเป็นต้องเรียกgrepหาสิ่งง่าย ๆ

หรือเป็นฟังก์ชั่น:

occur() while case "$1" in (*"$2"*) set -- \
        "${1#*"$2"}" "$2" "${3:-0}" "$((${4:-0}+1))";;
        (*) return "$((${4:-0}<${3:-1}))";;esac
        do : "${_occur:+$((_occur=$4))}";done

ใช้เวลา 2 หรือ 3 args ให้มากกว่าที่จะบิดเบือนผลลัพธ์ คุณสามารถใช้มันเหมือน:

_occur=0; occur ... . 2 && echo "count: $_occur"

... ซึ่งพิมพ์นับการเกิดขึ้นของ.ใน...ถ้ามันเกิดขึ้นอย่างน้อย 2 ครั้ง แบบนี้:

count: 3

ถ้า$_occurว่างเปล่าหรือunsetเมื่อมันถูกเรียกใช้มันจะไม่มีผลกับตัวแปรเชลล์เลยและreturn1 ถ้า"$2"เกิดขึ้นในเวลา"$1"น้อยกว่า"$3"นั้น หรือถ้าเรียกว่ามีเพียงสอง args ก็จะreturn1 เฉพาะในกรณีที่ไม่ได้อยู่ใน"$2" "$1"มิฉะนั้นจะส่งคืน 0

ดังนั้นในรูปแบบที่ง่ายที่สุดคุณสามารถ:

occur '' . && echo yay || echo shite

... ที่พิมพ์ ...

shite

...แต่...

occur . . && echo yay || echo shite

... จะพิมพ์ ...

yay

คุณอาจเขียนมันแตกต่างกันเล็กน้อยและละเว้นเครื่องหมายคำพูดรอบ$2ทั้งใน(*"$2"*)และ"${1#*"$2"}"คำสั่ง หากคุณทำเช่นนั้นคุณสามารถใช้เปลือก globs สำหรับการแข่งขันเช่นsh[io]teสำหรับการทดสอบการแข่งขัน


1
+1: เร็วกว่าแน่นอน ทำงานในbashและdash/ sh(และอาจเป็นอีกไม่กี่คน)
John WH Smith

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