В общем случае проблемы как это происходят из-за mistmatch между тем, что отправляет эмулятор терминала и что ожидает клиентское приложение.
Различные эмуляторы терминала имеют другую степень настраиваемости, таким образом ознакомление себя с эмуляцией tunables конкретной необходимо.
Клиентские приложения зависят от значения $TERM
который привык к терминалу поиска (эмулятор) возможности в terminfo
(или termcap
) база данных.
В Вашем случае Ваша emacs привязка использует явные последовательности таким образом $TERM
и terminfo не важны: определенный эмулятор терминала ожидается - когда Вы уже выяснили, a xterm
- совместимый.
Если Вы хотите удалить все строки, запускающиеся с %, помещенного, сохраняя первые две строки входа, Вы могли сделать:
sed -e 1,2b -e '/^%/d'
Хотя то же было бы более четким с awk
:
awk 'NR <= 2 || !/^%/'
Или, если Вы после производительности:
{ head -n 2; grep -v '^%'; } < input-file
Если Вы хотите сохранить первые две строки, соответствующие шаблону, в то время как они не могут быть первыми входа, awk
конечно, был бы более оптимальный вариант:
awk '!/^%/ || ++n <= 2'
С sed
, Вы могли использовать приемы как:
sed -e '/^%/!b' -e 'x;/xx/{h;d;}' -e 's/^/x/;x'
Таким образом, используйте пространство хранения для подсчета количества случаев шаблонов подобранным до сих пор. Не ужасно эффективный или четкий.
Я боюсь sed
один немного слишком просто для этого (не, что это было бы невозможно, скорее сложный - видят, например, sed sokoban для того, что может быть сделано).
Как насчет awk
?
#!/bin/awk -f
BEGIN { c = 0; }
{
if (/^%/) {
if (c++ < 3) {
print;
}
} else {
print;
}
}
Если можно полагаться на использование достаточно недавнего Bash (который поддерживает регулярные выражения), awk выше может быть переведен в:
#!/bin/bash -
c=0
while IFS= read -r line; do
if [[ $line =~ ^% ]]; then
if ((c++ < 3)); then
printf '%s\n' "$line"
fi
else
printf '%s\n' "$line"
fi
done
Можно также использовать sed
или grep
сделать сопоставление с образцом вместо =~
оператор.
[[
, можно использовать case $line in %*)
. Выполнение его этот путь с оболочками, особенно колотите, будет ужасно неэффективным. Используя циклы в оболочках обычно считается плохой практикой.
– Stéphane Chazelas
18.01.2013, 11:17
tr '\n' ';' < input | sed 's/% /##/3g' | tr ';' '\n' | sed '/##/d'
Я заменил символы новой строки''; для получения однострочной строки, затем повернул всех кроме первых двух случаев шаблона в маркировку ## с sed 's/pattern/##/3g' (замена от трети до последнего вхождения шаблона в строке), возвращенный''; к '\n' и наконец удаленным отмеченным строкам.
sed '/^%/{
3,$d}' '% 1
% 2
% 3
% 4
% 5
text1
text2
text3'
Один способ удалить дополнительные строки.
Править: мой ответ работает при том же условии как Stephane Chazelas
если строки % не произойдут сначала, то это не будет работать.
Компьютерный фанат, стреляющий из укрытия.
sed -n '/^% [^12]*$/!{
/^% [12][[:digit:]]\{1,\}/n
p}' file.txt
Будет работать независимо от где % number
строка найдена в потоке. Любая строка, которая запускается с %
и концы с любым количеством символов, кроме того, 1
или 2
, который мы инвертируем. Тот адрес соответствует чему-либо, кроме того, /% [A-Za-z3-9]*/
отъезд мертвой зоны. Числа между 10-29 распечатают все еще. Таким образом, мы вкладываем второй адрес, чтобы соответствовать тому диапазону и пропустить строку.
Но awk все еще был бы лучше.