grep trên một biến


58

Hãy nói rằng tôi có một biến

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

bây giờ tôi muốn grep bao nhiêu lần chọn xảy ra trong câu.

grep -ci "select" $line

Tôi đã thử nó, nhưng nó không hoạt động. Tôi cũng đã thử

grep -ci "select" "$line"

Nó vẫn không hoạt động. Tôi nhận được lỗi sau đây.

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

1
Bạn cần sử dụng herestring ...<<<"$line" . Lệnh grepđang mong đợi một tập tin thay thế
Valentin Bajrami

Câu trả lời:


85

Đã grepđọc về đầu vào tiêu chuẩn của nó. Đến đó, sử dụng một đường ống ...

$ echo "$line" | grep select

... hoặc một chuỗi ở đây ...

$ grep select <<< "$line"

Ngoài ra, bạn có thể muốn thay thế khoảng trắng bằng dòng mới trước khi grepping:

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

... Hoặc bạn có thể yêu cầu grepchỉ in trận đấu:

$ echo "$line" | grep -o select

Điều này sẽ cho phép bạn thoát khỏi phần còn lại của dòng khi có trận đấu.

Chỉnh sửa: Rất tiếc, đọc quá nhanh, cảm ơn Marco . Để đếm số lần xuất hiện, chỉ cần đặt bất kỳ trong số này đến wc(1);)

Một chỉnh sửa khác được thực hiện sau bình luận của lzkata , trích dẫn $linekhi sử dụng echo.


3
Vì OP muốn đếm số lần xuất hiện của một chuỗi, bạn có thể thêm một wcđể hoàn thành nhiệm vụ:grep -o <string> <<< "$variable" | wc -l
Marco

2
Sử dụng echo "$line"để duy trì các dòng mới hiện có thay vì tạo các dòng mới vớitr
Izkata

Sự sẵn có của Chuỗi ở đây là gì? Nó có cần Bash hay shell khác không?

Theo Wikipedia , ở đây các chuỗi có sẵn trong bash, ksh và zsh (nhưng tôi cho rằng có thể có các chuỗi khác).
John WH Smith

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

Bạn không cần phải gọi grepcho một điều đơn giản như vậy.

Hoặc như một chức năng:

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

Phải mất 2 hoặc 3 đối số. Cung cấp nhiều hơn thế sẽ làm lệch kết quả của nó. Bạn có thể sử dụng nó như:

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

... In số lần xuất hiện .trong ...nếu nó xảy ra ít nhất 2 lần. Như thế này:

count: 3

Nếu $_occurlà trống hoặc unsetkhi nó được gọi thì nó sẽ không ảnh hưởng đến các biến shell và return1 nếu "$2"xảy ra "$1"ít hơn số "$3"lần. Hoặc, nếu được gọi chỉ với hai đối số, nó sẽ returnchỉ 1 nếu "$2"không tham gia "$1". Khác nó trả về 0.

Và vì vậy, ở dạng đơn giản nhất, bạn có thể làm:

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

... mà in ...

shite

...nhưng...

occur . . && echo yay || echo shite

... sẽ in ...

yay

Bạn cũng có thể viết nó một chút khác nhau và bỏ qua các trích dẫn xung quanh $2trong cả câu lệnh (*"$2"*)"${1#*"$2"}"câu lệnh. Nếu bạn làm điều đó thì bạn có thể sử dụng các khối vỏ cho các trận đấu như sh[io]teđối với bài kiểm tra trận đấu.


1
+1: Nhanh hơn, thực sự. Hoạt động trong bashdash/ sh(và có lẽ một vài người khác).
John WH Smith

@JohnWHSmith - chỉnh sửa tốt hơn, nhưng vẫn chỉ là di động.
mikeerv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.