Это самое портативное решение, будет работать даже на старых оболочках Bourne и оболочке Korn
#!/bin/bash
case "abcd" in
*$1*) echo "It's a substring" ;;
*) echo "Not a substring" ;;
esac
Пример прогона:
$ ./case_substr.sh "ab"
It's a substring
$ ./case_substr.sh "whatever"
Not a substring
Обратите внимание, что вам не нужно специально использовать echo, вы можете использовать exit 1 и exit 0 для обозначения успеха или сбоя.
То, что мы могли бы сделать, также - создать функцию (который может быть использован в больших сценариях, если необходимо) с конкретными значениями возврата (0 по совпадению, 1 не соответствует):
$ ./substring_function.sh
ab is substring
$ cat substring_function.sh
#!/bin/sh
is_substring(){
case "$2" in
*$1*) return 0;;
*) return 1;;
esac
}
main(){
if is_substring "ab" "abcdefg"
then
echo "ab is substring"
fi
}
main $@
$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"
it's a substring
Этот конкретный подход полезен для операторов if-else в bash. Также в основном переносится
$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"
it is a substring
$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"
it is a substring
$ ruby -e ' puts "is substring" if ARGV[1].include? ARGV[0]' "ab" "abcdef"
is substring
Предполагая, что ваш исходный файл - tmp.txt,
grep -iv '.*this.*this.*this.*this' tmp.txt | grep -i '.*this.*this.*this.*'
Левый grep выводит все строки, у которых нет 4 или более нечувствительных к регистру вхождений «this» в tmp.txt.
Результат передается вправо grep, который выводит все строки с 3 или более вхождениями в результат левого grep.
Обновление: благодаря @Muru, вот лучшая версия этого решения,
grep -Eiv '(.*this){4,}' tmp.txt | grep -Ei '(.*this){3}'
заменить 4 на n + 1 и 3 на n.
В python это выполнит задание:
#!/usr/bin/env python3
s = """How to get This line that this word repeated 3 times in THIS line?
But not this line which is THIS word repeated 2 times.
And I will get This line with this here and This one
A test line with four this and This another THIS and last this"""
for line in s.splitlines():
if line.lower().count("this") == 3:
print(line)
выдает:
How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one
Или читать из файла с файлом в качестве аргумента:
#!/usr/bin/env python3
import sys
file = sys.argv[1]
with open(file) as src:
lines = [line.strip() for line in src.readlines()]
for line in lines:
if line.lower().count("this") == 3:
print(line)
Вставьте скрипт в пустой файл, сохраните его как find_3.py, запустите его командой: python3 /path/to/find_3.py <file_withlines>
Конечно, слово «это» можно заменить на любое другое слово (или другая строка или строка), а число вхождений в строке может быть установлено на любое другое значение в строке:
if line.lower().count("this") == 3:
Если файл был бы большим (сотни тысяч / миллионы строк), код ниже был бы быстрее; он считывает файл на строку, а не сразу загружает файл:
#!/usr/bin/env python3
import sys
file = sys.argv[1]
with open(file) as src:
for line in src:
if line.lower().count("this") == 3:
print(line.strip())
Вы можете сыграть бит с awk для этого:
awk -F"this" 'BEGIN{IGNORECASE=1} NF==4' file
Это возвращает:
How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one
Предполагая, что строки хранятся в файле с именем FILE:
while read line; do
if [ $(grep -oi "this" <<< "$line" | wc -w) = 3 ]; then
echo "$line";
fi
done <FILE
Если вы находитесь в Vim:
g/./if len(split(getline('.'), 'this\c', 1)) == 4 | print | endif
Это будет просто печатать согласованные строки.
Однострочное решение Ruby:
$ ruby -ne 'print $_ if $_.chomp.downcase.scan(/this/).count == 3' < input.txt
How to get This line that this word repeated 3 times in THIS line?
And I will get This line with this here and This one
Работает довольно просто: мы перенаправляем файл на stdin ruby, ruby получает строку от stdin, очищает его с помощью chomp и downcase , и scan().count дает нам количество вхождений подстроки.