grep на переменную

58

Допустим, у меня есть переменная

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

Теперь я хочу понять, сколько раз происходит выбор в предложении.

grep -ci "select" $line

Я попробовал это, но это не сработало. Я тоже пробовал

grep -ci "select" "$line"

Это все еще не работает. Я получаю следующую ошибку.

grep: This is where we select from a table.: No such file or directory
gkmohit
источник
1
Вам нужно использовать здесь ...<<<"$line" . Команда grepожидает файл вместо этого
Валентин Байрами
stackoverflow.com/questions/2106526/…
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:

85

Были ли grepпрочитать на стандартный ввод. Там вы идете, используя трубу ...

$ echo "$line" | grep select

... или здесь строка ...

$ grep select <<< "$line"

Кроме того, вы можете заменить пробелы на новые строки перед grepping:

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

... или вы можете попросить grepраспечатать только матч:

$ echo "$line" | grep -o select

Это позволит вам избавиться от остальной части линии, когда есть совпадение.

Редактировать: Ой, читай слишком быстро, спасибо Марко . Для того, чтобы сосчитать случаи, просто отправьте любой из них wc(1);)

Еще одно изменение, сделанное после комментария lzkata , цитирование $lineпри использовании echo.

Джон У. Смит
источник
3
Поскольку ОП хочет подсчитать количество вхождений строки, вы можете добавить a wcдля завершения задачи:grep -o <string> <<< "$variable" | wc -l
Марко
2
Используйте echo "$line"для сохранения существующих новых строк вместо создания с помощьюtr
Izkata
Что такое доступность строки Here? Требуется ли Bash или другая оболочка?
Согласно Википедии , здесь доступны строки в bash, ksh и zsh (но я предполагаю, что могут быть и другие).
Джон У. С. Смит
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 аргумента. Предоставление большего, чем это, искажает его результаты. Вы можете использовать его как:

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

... который печатает число вхождений .в, ...если это происходит по крайней мере 2 раза. Нравится:

count: 3

Если $_occurпусто или unsetкогда оно вызывается, то это не повлияет на переменные оболочки вообще и return1, если "$2"происходит "$1"меньше, чем "$3"раз. Или, если вызывается только с двумя аргументами, он будет равен return1, только если "$2"его нет "$1". В противном случае возвращается 0.

И так, в простейшем виде вы можете сделать:

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

... который печатает ...

shite

...но...

occur . . && echo yay || echo shite

... напечатает ...

yay

Вы также можете написать его немного по- другому и опускать кавычки $2в обоих (*"$2"*)и "${1#*"$2"}"заявления. Если вы сделаете это, то вы можете использовать оболочки оболочки для совпадений, например, sh[io]teдля теста совпадения.

mikeserv
источник
1
+1: быстрее, действительно. Работает в bashи dash/ sh(и, возможно, несколько других).
Джон У. С. Смит,
@JohnWHSmith - редактирование лучше, но все же так же переносимо.
mikeserv