Я хотел бы напечатать n-е совпадение поиска sed, которое основано на двух шаблонах, как показано ниже:
sed -n '/start here/,/end here/p' 'testfile.txt'
Скажем, что testfile.txt
содержит текст ниже:
и что я не хочу печатать нули между двумя шаблонами.
На основе приведенной выше команды я получу все совпадения между шаблонами, а ее вывод показан ниже:
start here
0000000
0000000
end here
start here
123
1234
12345
123456
end here
start here
00000000
end here
В то время как мой желаемый результат:
start here
123
1234
12345
123456
end here
Учтите, что строки должны быть напечатаны как в testfile.txt
, а не соединены.
Я просто переключился бы на другой инструмент. Perl, например:
perl -ne '$k++ if /Pattern1/; if(/Pattern1/ .. /Pattern2/){print if $k==3}' file
Это распечатает 3-е соответствие. Изменитесь $k==3
к любому значению Вы хотите. Логика:
$k++ if /Pattern1/
: увеличьте значение переменной $k
тем, если эта строка соответствует Pattern1
.if(/Pattern1/ .. /Pattern2/){print if $k==3}
: если эта строка в диапазоне /Pattern1/
кому: /Pattern2/
, распечатайте его, но только если $k
3. Измените это значение на то, какой бы ни соответствие Вы хотите. Вы могли перенести это в небольшую функцию оболочки, чтобы смочь получить Энное соответствие более легко:
getNth(){
pat1="$1"
pat2="$2"
n="$3"
file="$4"
perl -ne '$k++ if /'"$pat1"'/;if(/'"$pat1"'/ .. /'"$pat2"'/){print if $k=='"$n"'}' file
}
Вы могли затем выполнить его как это:
getNth Pattern1 Pattern2 3 'huge file.txt'
Используя Ваши данные в качестве примера:
$ perl -lne '$k++ if /start here/;if(/start here/ .. /end here/){print if $k==2}' testfile.txt
start here
123
1234
12345
123456
end here
Или:
$ getNth 'start here' 'end here' 2 testfile.txt
start here
123
1234
12345
123456
end here
Только для забавы, вот другой подход жемчуга:
$ perl -lne '($k++,$l++) if /start here/; print if $l && $k==2; $l=0 if /end here/' testfile.txt
start here
123
1234
12345
123456
end here
Или, если Вам нравится играть в гольф (благодарит @simlev):
perl -ne 'print if /^start here$/&&++$k==2../^end here$/' testfile.txt
Я бы решил это с Perl, как разумно предполагает @terdon . Или с AWK:
awk '/start here/&&++k==2,/end here/' testfile.txt
Если бы мне пришлось использовать sed в одиночку (как указывает OP в комментарии), я бы придумал что-то гораздо более запутанное, менее читаемое и менее настраиваемое:
[ 111]